home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / flight / flight.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  78.5 KB  |  3,558 lines

  1. /*
  2.  * Copyright 1984-1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  *  flight/flight.c $Revision: 1.46 $
  20.  */
  21.  
  22.  
  23. #include "flight.h"
  24. #include "light.h"
  25. #include "udpbrdcst.h"
  26. #include <sys/param.h>
  27. #include <sys/types.h>
  28. #include <sys/times.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <signal.h>
  32.  
  33.  
  34. /*
  35.  *  general status
  36.  */
  37.  
  38. /*
  39.  *  timing info
  40.  */
  41. int int_tps = 20;    /* integer ticks per second */
  42. float tps = 20;        /* ticks per second */
  43. short tick_counter;    /* counts the loop ticks    */
  44. struct tms tms_start_buf, tms_end_buf;    /* timer buffer */
  45. int time_start, time_end;            /* start/end times */
  46.  
  47. /*
  48.  *  effects of timing
  49.  */
  50. float gravity = 1;        /* the effect of gravity relative to tps */
  51. float fps_knots;    /* fps to knots conversion factor based on tps */
  52.  
  53. int number_planes;    /* number of planes in game    */
  54.  
  55.  
  56. /*
  57.  *  screen and window info
  58.  */
  59. int xmaxscreen = 0;
  60. int ymaxscreen = 0;
  61. int xorigin, yorigin;
  62. int xmaxwindow, ymaxwindow;
  63. int xmiddle, ymiddle;
  64. int zminscreen, zmaxscreen;
  65. int inst_x1, inst_x2, inst_y1, inst_y2;
  66. int report_x1, report_x2, report_y1, report_y2;
  67.  
  68. /*
  69.  *  display state info
  70.  */
  71. int in_cmode = FALSE;
  72. int force_cmode = FALSE;
  73. int force_rgb = FALSE;
  74. int bits_cmode = 6;            /* maximum of 6 bits used */
  75. int bits_over = 2;
  76. int bits_under = 2;
  77. long over_drawmode = PUPDRAW;        /* OVERDRAW or PUPDRAW */
  78. int ms_samples = 0;
  79.  
  80. /*
  81.  *  mouse and spaceball positions
  82.  */
  83. long mousex, mousey, sbtx, sbtz;
  84.  
  85.  
  86. /*
  87.  *  misc
  88.  */
  89. int i;
  90. int errno;
  91. static char charbuf[80];    /* char buffer */
  92. Matrix identmat;        /* identity matrix */
  93. char status_text[60];
  94.  
  95. char *WEAPON_NAME[] = {"rocket", "sidewinder", "20mm cannon",
  96.                "Surface to Air Missile"};
  97. extern float ro[], fuel_consump();    /* air density table    */
  98.  
  99. int oldthrust;   /* thing for constant thrust sound */
  100. int bell=1;      /* keyboard beep on */
  101.  
  102. int restart = 1;
  103. #define START1 1
  104. #define START2 2
  105. #define START3 3
  106. #define START4 4
  107.  
  108.  
  109. /*
  110.  *  flags
  111.  */
  112. short debug;            /* TRUE if in debug mode */
  113. short dogfight;            /* TRUE if dogfight */
  114. short shadow;            /* TRUE if shadow */
  115. short radar;            /* TRUE if radar */
  116. short hud;            /* TRUE if hud, else meters */
  117. short threat_mode;        /* TRUE if threats envelopes */
  118. short timeit;            /* TRUE if displaying timing info */
  119. short test_mode;        /* test mode uses no fuel */
  120. short dials = FALSE;        /* TRUE if using dials */
  121. short new_inst = TRUE;        /* TRUE if using new instroments */
  122. short show_help = FALSE;    /* TRUE if displaying help */
  123.  
  124.  
  125. /*
  126.  *  geomety objects
  127.  */
  128. object_t *runwayobj;
  129. object_t *lightsobj;
  130. object_t *hillsobj;
  131. object_t *mtnsobj;
  132. object_t *buildingsobj;
  133. object_t *planeobj[9];
  134. object_t *swobj;
  135. object_t *threatobj;
  136. object_t *planeboxobj;
  137. char datadir[108];
  138. char sounddir[108];
  139. char objdir[108];
  140. char objfname[128];
  141. grid_t *hillsgrid;
  142.  
  143. obj_list_t sort_obj[MAX_OBJS];
  144. obj_list_t sort_plane[MAX_PLANES];
  145. obj_list_t sort_missile[MAX_PLANES];
  146. int obj_count;
  147.  
  148.  
  149. /*
  150.  *  The following are used to adjust for frame rate speed changes
  151.  */
  152. float vx_add,        /* plane velocity add per frame */
  153.       vy_add,
  154.       vz_add;
  155. float missile_vx_add,    /* missile velocity add per frame */
  156.       missile_vy_add,
  157.       missile_vz_add;
  158. float tps_add;        /* tps (ticks per second) add per frame */
  159.  
  160.  
  161.  
  162.  
  163. /*
  164.  *  plane design parameters
  165.  */
  166. char *plane_type;        /* plane type (i.e. "F-15") */
  167. float s;            /* wing area in sq. feet */
  168. float W;            /* weight of plane in lbs. */
  169. float fuel_weight;        /* weight of fuel */
  170. float Mthrust;            /* maximum thrust */
  171. float b;            /* wing span in feet */
  172. float ef;            /* efficiency factor */
  173. float Fmax;            /* maximum flap deflection */
  174. float Smax;            /* maximum spoiler deflection */
  175. float ELEVF;            /* elevator rate in degrees/sec */
  176. float ROLLF;            /* roll rate (both at 300 mph) */
  177. float pilot_eye[4] = {0.0, 0.0, 0.0, 1.0};    /* pilots eye position */
  178. float Lmax;            /* maximum lift before wing breaks */
  179. float Lmin;            /* minimum lift before wing breaks */
  180. float plane_height;        /* height of plane midpoint */
  181. int MAX_RK, MAX_SW;        /* max rockets and sidewinders */
  182. int MIN_LIFT_SPEED;        /* minimum lift-up speed fps */
  183. float swpos[4][4] = {{0.0, 0.0, 0.0, 1.0},    /* position of sidewinders on */
  184.              {0.0, 0.0, 0.0, 1.0},    /* plane */
  185.              {0.0, 0.0, 0.0, 1.0},
  186.              {0.0, 0.0, 0.0, 1.0}};
  187. float rkpos[4][4] = {{0.0, 0.0, 0.0, 1.0},    /* position of rockets on */
  188.              {0.0, 0.0, 0.0, 1.0},    /* plane */
  189.              {0.0, 0.0, 0.0, 1.0},
  190.              {0.0, 0.0, 0.0, 1.0}};
  191.  
  192. /*
  193.  *  computed plane design parameters
  194.  */
  195. float gefy;            /* maximum height for ground effect */
  196. float fuel_rate;        /* fuel consumption rate */
  197. float ipi_AR;            /* 1.0 / pi * wing Aspect Ratio */
  198. float ie_pi_AR;            /* 1.0 / pi * AR * efficiency */
  199.  
  200. /*
  201.  *  variable plane design parameters
  202.  */
  203. float inverse_mass;        /* 1.0 / mass of plane */
  204. float Lmax_g;            /* Lmax * gravity */
  205. float Lmin_g;            /* Lmin * gravity */
  206.  
  207. /*
  208.  *  plane state
  209.  */
  210. Matrix ptw;                /* my ptw matrix */
  211. float (*my_ptw)[4];            /* pointer to my matrix    */
  212. int sidewinders, rockets;        /* number of armaments        */
  213. float rudder, elevator, rollers;    /* control settings        */
  214. float vx, vy, vz;            /* plane velocity */
  215. int twist, elevation, azimuth;        /* plane orientation        */
  216. int roll_speed;                /* roll, elevation, azimuth speeds */
  217. int elevation_speed;            /* in 10'ths degrees per tick    */
  218. int azimuth_speed;
  219. int flaps, spoilers;            /* flap and spoiler settings    */
  220. float lift;                /* lift acceleration        */
  221. int airspeed, last_airspeed;
  222. int climbspeed, last_climbspeed;
  223. short g_limit;                /* TRUE if wing g-limit is hit    */
  224. short wing_stall;            /* TRUE if wing is stalling    */
  225. short on_ground;            /* TRUE if plane is on ground    */
  226. short on_hill;                /* TRUE if plane is on hill    */
  227. short wheels;                /* TRUE if the wheels are down    */
  228. short wheels_retracting;        /* used only            */
  229. short landing_gear_stuck;        /* >= 0 if the gear is stuck    */
  230. int fuel;                /* fuel (0 - 12800)        */
  231. int thrust;                /* thrust (0 - 100)        */
  232. int throttle;                /* throttle (0 - 100)        */
  233. int max_throttle;            /* upper limit on engines    */
  234. int min_throttle;            /* lower limit on engines    */
  235. float last_px, last_py, last_pz;    /* last plane position        */
  236. float max_cl, min_cl;            /* max and min coefficient of lift */
  237. float tilt_factor;            /* wing angle tilt due to flaps    */
  238. float Splf, Spdf;            /* spoiler factors on lift and drag */
  239. float mach;                /* mach #, crest critical #, ratio */
  240. float Cdp;                /* coefficient of parasitic drag */
  241.  
  242. /*
  243.  *  autopilot state
  244.  */
  245. short autopilot_on;            /* TRUE in autopilot mode */
  246. int target_twist;            /* target twist for autopilot */
  247. int target_speed;            /* target speed for autopilot */
  248. int target_climb;            /* target climb for autopilot */
  249.  
  250. /*
  251.  *  crash state
  252.  */
  253. int stick_xadd, stick_yadd;
  254. int sb_xadd, sb_yadd;
  255.  
  256. /*
  257.  *  missile status
  258.  */
  259. long missile_target;        /* plane my missile is after    */
  260. long missile_target_timeout;    /* timeout for missile tracking */
  261. float missile_vx,        /* missile velocity */
  262.       missile_vy,
  263.       missile_vz;
  264. float missile_eye[4] = {0.0, 5.0, 0.0, 1.0};    /* missiles eye position */
  265. int mvpos = 0;
  266. int mvspos = 0;
  267. int mvfollow = 1;
  268.  
  269. /*
  270.  *  wingman history
  271.  */
  272. int wm_twist[10];
  273. int wm_elevation[10];
  274. int wm_azimuth[10];
  275. float wm_x[10], wm_y[10], wm_z[10];
  276. int wmpos = 0;
  277. int wmspos = 0;
  278. int wmfollow = 5;
  279.  
  280. /*
  281.  *  view state
  282.  */
  283. short view_switch;
  284. int wingman_view = 0;
  285. int missile_view = 0;
  286. int cam_az = 0, cam_el = 900;
  287. float cam_x, cam_y, cam_z;
  288. float cam_dist = 100.0;            /* stuff for plane camera */
  289. int fov = 600;                /* field of view */
  290. int plane_fov, tower_fov;        /* plane, tower field of view */
  291. float ar = 2.0;                /* aspect rationo */
  292. long dist_for_lines;            /* distance to draw building lines */
  293. int view_angle;                /* rotation of pilot's head */
  294. int fogit = FALSE;
  295. int texit = FALSE;
  296. float eye_x, eye_y, eye_z;        /* eye position     */
  297. float current_eye[4];            /* current eye position */
  298. float frustum[4][4];
  299. float clip_planes[4][4];
  300.  
  301.  
  302. flight(argc, argv)
  303.     int argc;
  304.     char *argv[];
  305. {
  306.     register int itemp;        /* temp integer variable    */
  307.  
  308.     float temp;                /* temp float variable    */
  309.  
  310.     register Plane ptemp, pp;        /* my plane data structure    */
  311.  
  312.  
  313. static char usage[] = "Usage: flight  [-bdhnsO] [-i filename] [-o filename] [-D datadirectory] [-T ttl] [-I addr]\n";
  314.  
  315.     test_mode = FALSE;
  316.  
  317.     strncpy(datadir, DATADIR, 80);
  318.  
  319.     if (strcmp(argv[0] + strlen(argv[0]) - strlen("shadow"), "shadow") == 0)
  320.     {
  321.     shadow = TRUE;
  322.     dogfight = TRUE;
  323.     }
  324.     else if (strcmp(argv[0] + strlen(argv[0]) - strlen("radar"), "radar") == 0)
  325.     {
  326.     radar = TRUE;
  327.     dogfight = TRUE;
  328.     }
  329.     else if (strcmp(argv[0] + strlen(argv[0]) - strlen("dog"), "dog") == 0)
  330.     dogfight = TRUE;
  331.  
  332.     /*
  333.      *  parse command line arguments
  334.      */
  335.     while (--argc > 0 && **++argv == '-')
  336.     {
  337.     register char *token;
  338.  
  339.     for (token = argv[0] + 1; *token; token++)
  340.     switch (*token)
  341.     {
  342.         case 'i':
  343.         if (--argc > 0)
  344.         {
  345.             infile = *++argv;
  346.             dogfight = TRUE;
  347.         }
  348.         break;
  349.         case 'o':
  350.         if (--argc > 0)
  351.         {
  352.             outfile = *++argv;
  353.             dogfight = TRUE;
  354.         }
  355.         break;
  356.         case 'b':    /* broadcast */
  357.         multicast = FALSE;
  358.         break;
  359.         case 'I':
  360.         if (--argc > 0)
  361.             mcast_ifaddr = *++argv;
  362.         break;
  363.         case 'T':
  364.         if (--argc > 0)
  365.             mcast_ttl = atoi(*++argv);
  366.         break;
  367.         case 'd':
  368.         dials = TRUE;
  369.         break;
  370.         case 'n':
  371.         dogfight = TRUE;
  372.         break;
  373.         case 'r':
  374.         radar = TRUE;
  375.         dogfight = TRUE;
  376.         break;
  377.         case 's':
  378.         shadow = TRUE;
  379.         dogfight = TRUE;
  380.         break;
  381.         case 'D':
  382.         if (--argc > 0)
  383.         {
  384.             strncpy(datadir, *++argv, 58);
  385.             strcat(datadir, "/");
  386.         }
  387.         break;
  388.         case 'h':
  389.         hud = TRUE;
  390.         break;
  391.         case 'O':
  392.         new_inst = FALSE;
  393.         break;
  394.         case 'C':
  395.         force_cmode = TRUE;
  396.         break;
  397.         case '4':
  398.         bits_cmode = 4;
  399.         break;
  400.         case 'R':
  401.         force_rgb = TRUE;
  402.         break;
  403. #ifdef EXPER
  404.         case 'X':
  405.         if (--argc > 0)
  406.             xmaxscreen = atoi(*++argv);
  407.         if (--argc > 0)
  408.             ymaxscreen = atoi(*++argv);
  409.         break;
  410. #endif
  411.         default:
  412.         fprintf(stderr, "unknown option %c\n", *token);
  413.         break;
  414.     }
  415.     }
  416.     if (argc > 0)
  417.     {
  418.     fprintf(stderr, usage);
  419.     exit(0);
  420.     }
  421.  
  422.     eye_x = TOWER_X;
  423.     eye_y = TOWER_Y;
  424.     eye_z = TOWER_Z;
  425.  
  426.     /*
  427.      *  initialize toggle settings
  428.      */
  429.     fogit = FALSE;
  430.     {
  431.     char buf[32];
  432.     gversion(buf);
  433.     texit = (strncmp(buf, "GL4DXG-", 7) != 0) &&
  434.         (strncmp(buf, "GL4DLG-", 7) != 0) &&
  435.         (strncmp(buf, "GL4DNP-", 7) != 0) &&
  436.         (getgdesc(GD_TEXTURE) > 0);
  437.     }
  438.  
  439.     if (shadow)
  440.     {
  441.     init_graphics("shadow");
  442.     InitComm("shadow");
  443.     }
  444.     else if (radar)
  445.     {
  446.     init_graphics("radar");
  447.     InitComm("radar");
  448.     }
  449.     else if (dogfight)
  450.     {
  451.     init_graphics("dog");
  452.     InitComm("plane");
  453.     }
  454.     else
  455.     {
  456.     init_graphics("flight");
  457.     for (itemp=0; itemp < 2; itemp++)
  458.     {
  459.         pp = (Plane)malloc(sizeof(struct plane));
  460.         pp->alive = -1;
  461.         pp->won = 0;
  462.         pp->lost = 0;
  463.         PLANE_ID(pp) = 23;
  464.         strcpy(pp->myname, "myself");
  465.         planes[itemp] = pp;
  466.     }
  467.     plane_hists[0] = (Plane_hist)malloc(sizeof(struct plane_hist));
  468.     }
  469.  
  470.     pp = planes[0];
  471.  
  472.     qreset();
  473.  
  474.     my_ptw = ptw;
  475.  
  476.     if (dials)
  477.     init_dials();
  478.  
  479.     redraw_screen();
  480.     reset_meters();
  481.  
  482.     if (shadow)
  483.     {
  484.     number_planes = 0;
  485.     display_shadow_help();        /* I do a swapbuffers */
  486.     }
  487.     else if (radar)
  488.     {
  489.     number_planes = 0;
  490.     display_radar_help();        /* I do a swapbuffers */
  491.     }
  492.     else
  493.     {
  494.     number_planes = 2;
  495.     display_help();            /* I do a swapbuffers */
  496.     }
  497.  
  498.     argc = 0;
  499.  
  500.     time_start = times(&tms_start_buf);
  501.  
  502.     if (!radar)
  503.     read_objects(TRUE);
  504.     wait_for_input();
  505.  
  506. do_restart:
  507.     if (shadow)
  508.     {
  509.     shadow_start();
  510.     shadow_loop();
  511.     }
  512.     else if (radar)
  513.     {
  514.     radar_start();
  515.     radar_loop();
  516.     }
  517.     else
  518.     {
  519.     flight_start();
  520.     flight_loop();
  521.     }
  522.  
  523.     if (restart)
  524.     goto do_restart;
  525. }
  526.  
  527.  
  528.  
  529. /*
  530.  *  start up code specific to flight
  531.  */
  532. flight_start()
  533. {
  534.     Plane pp = planes[0];
  535.     int itemp;
  536.  
  537.     switch(restart)
  538.     {
  539.     case START1:            /* come here for default start */
  540.     default:
  541.         pp->x = START_X;
  542.         pp->y = START_Y;
  543.         pp->z = START_Z;
  544.         azimuth = START_AZIMUTH;
  545.         vz = 0.0;
  546.         wheels = TRUE; pp->wheels = 0;
  547.         break;
  548.     case START2:            /* end of runway start */
  549.         pp->x = 0.0;
  550.         pp->y = START_Y;
  551.         pp->z = -500.0;
  552.         azimuth = 0;
  553.         vz = 0.0;
  554.         wheels = TRUE; pp->wheels = 0;
  555.         break;
  556.     case START3:            /* airborn start */
  557.         pp->x = flight_random(20000);
  558.         pp->y = 8000 + flight_random(6000);
  559.         pp->z = flight_random(20000);
  560.         azimuth = flight_random(3600);
  561.         vz = (flight_random(60)-80)/fps_knots;
  562.         wheels = FALSE; pp->wheels = 10;
  563.         break;
  564.     case START4:            /* used for threat runs */
  565.         pp->x = flight_random(20000);
  566.         pp->y = 10000 + flight_random(5000);
  567.         pp->z = 100000.0;
  568.         azimuth = 0;
  569.         vz = (flight_random(60)-160)/fps_knots;
  570.         wheels = FALSE; pp->wheels = 10;
  571.         break;
  572.     }
  573.     restart = 0;
  574.  
  575.     for (itemp = number_planes-1; itemp >= 0; itemp--)
  576.     planes[itemp]->alive = -1;
  577.     number_planes = 1;
  578.     reset_meters();
  579.     landing_gear_stuck = -1;        /* can toggle landing gear    */
  580.     test_mode = FALSE;
  581.  
  582.  
  583.     setvaluator(MOUSEX, mousex = xmiddle, 0, xmaxscreen);
  584.     setvaluator(MOUSEY, mousey = ymiddle, 0, ymaxscreen);
  585.  
  586.     select_plane();
  587.  
  588.     read_objects(FALSE);
  589.  
  590.     pp->y += plane_height;    /* add plane_height to plane elevation */
  591.  
  592.     Cdp = .015;                /* coefficient of parasitic drag*/
  593.     ipi_AR = 1.0/(3.1415927 * b*b/s);    /* 1.0 / pi * wing Aspect Ratio    */
  594.     ie_pi_AR = ipi_AR/ef;        /* 1.0 / pi * AR * efficiency    */
  595.     ROLLF *= 10.0/(30.0 * 400.0);
  596.     ELEVF *= 10.0/(20.0 * 400.0);
  597.  
  598.     debug = timeit = FALSE;
  599.     autopilot_on = wheels = wing_stall = FALSE;
  600.     tick_counter = 2;            /* force text display    */
  601.     throttle = thrust = pp->thrust = 0;
  602.     roll_speed = elevation_speed = azimuth_speed = 0;
  603.     rudder = elevator = rollers = 0.0;
  604.     airspeed = last_airspeed = climbspeed = last_climbspeed = 0;
  605.     on_ground = (pp->y - plane_height) <= 4.0;
  606.     on_hill = FALSE;
  607.     gefy = .7 * b;
  608.     max_throttle = 100;
  609.     min_throttle = on_ground?-max_throttle:0;
  610.     vx = vy = vx_add = vy_add = vz_add = 0.0;
  611.     lift = 0.0;    mach = 0.0;
  612.     sidewinders = MAX_SW;
  613.     rockets = MAX_RK;
  614.     pp->mstatus = 0;
  615.     pp->weapon_state = PS_WEAPONS >> PS_W_SHIFT;
  616.     missile_target = NULL_PLANE_ID;
  617. #define compute_mass() (G_ACC / \
  618.     (W + fuel/12800.0*fuel_weight + ((sidewinders+rockets)<<9)))
  619.     fuel = 100 << 7;
  620.     inverse_mass = compute_mass();
  621.  
  622.     view_switch = PLANE_VIEW;            /* view from plane    */
  623.     if (hud)
  624.     plane_fov = tower_fov = 400;
  625.     else
  626.     plane_fov = tower_fov = 360;
  627.     reset_fov(plane_fov);
  628.  
  629.     last_py = pp->y;
  630.     pp->elevation = elevation = 0;
  631.     pp->twist = twist = 0;
  632.     pp->azimuth = azimuth;
  633.     pp->status = MSTART;
  634.     pp->alive = int_tps << 2;
  635.     flaps = spoilers = 0;
  636.     view_angle = 0;
  637.     fuel_rate = fuel_consump(Mthrust, W);
  638.     rebuild_status();
  639.  
  640.     /*
  641.      *  init wingman info
  642.      */
  643.     for (wmpos = 0; wmpos < 10; wmpos++)
  644.     {
  645.     wm_x[wmpos] = pp->x;
  646.     wm_y[wmpos] = pp->y;
  647.     wm_z[wmpos] = pp->z;
  648.     wm_twist[wmpos] = twist;
  649.     wm_elevation[wmpos] = elevation;
  650.     wm_azimuth[wmpos] = azimuth;
  651.     }
  652.     wmspos = wmfollow;
  653.     wmpos = 0;
  654.  
  655.     if (dogfight || shadow)
  656.     {
  657.     for (itemp=0; itemp < MAX_PLANES; itemp++)
  658.         get_indata(0);        /* read all input data    */
  659.     reset_meters();
  660.     display_score();
  661.     }
  662.  
  663.     if (on_ground)
  664.     {
  665.     qenter(KEYBD, 'f');        /* flaps up 1 notch    */
  666.     qenter(KEYBD, 'f');        /* flaps up 1 notch    */
  667.     qenter(KEYBD, 'f');        /* flaps up 1 notch    */
  668.     Cdp *= 3.0;
  669.     }
  670.     else
  671.     {
  672.     throttle = thrust = pp->thrust = max_throttle;
  673.     qenter(KEYBD, 'F');
  674.     }
  675.     if (on_ground || landing_gear_stuck > 0)
  676.     qenter(KEYBD, 'l');    /* put wheels down    */
  677. #ifdef AUDIO
  678.     pitch_thrust((float)(oldthrust = pp->thrust)/100.0);
  679. #endif
  680. }
  681.  
  682.  
  683.  
  684.  
  685. /*
  686.  *  main loop for flight
  687.  */
  688. flight_loop()
  689. {
  690.     unsigned char frame_count = 0;    /* count of frames */
  691.     int itemp;
  692.     Plane pp = planes[0], ptemp;
  693.  
  694.  
  695.     while (!restart)
  696.     {
  697.     clearz();    /* do this while all the calculations are happening */
  698.     if (pp->y <= 10.0 && pp->status <= MEXPLODE)
  699.     {
  700.         cpack(0x0);
  701.         clear();
  702.     }
  703.  
  704.  
  705.     if (dials)
  706.         check_dials();
  707.  
  708. #ifdef AUDIO
  709.     if (pp->status > MEXPLODE) play_thrust();
  710. #endif
  711.  
  712.     read_queue();
  713.  
  714.     /*
  715.      *  update time
  716.      */
  717.     if (!frame_count)
  718.         update_ftime();        /* every 256 frames */
  719.     frame_count++;
  720.  
  721.     /****************************************************************
  722.     /*    handle retractable landing gear
  723.     /****************************************************************/
  724.     if (wheels_retracting > 0)        /* going up    */
  725.     {
  726.         pp->wheels++;
  727.         if (pp->wheels >= 10)
  728.         {
  729.         pp->wheels = 10;
  730.         wheels_retracting = 0;
  731.         }
  732.     }
  733.     else if (wheels_retracting < 0)        /* going down    */
  734.     {
  735.         pp->wheels--;
  736.         if (pp->wheels <= 0)
  737.         {
  738.         pp->wheels = 0;
  739.         wheels_retracting = 0;
  740.         }
  741.     }
  742.  
  743.     /****************************************************************/
  744.     /*    process incoming data packets
  745.     /****************************************************************/
  746.     pp->alive = int_tps << 2;    /* always make me alive        */
  747.     if (pp->status > MEXPLODE)
  748.         if (pp->status > 65000)    /* increment my timestamp    */
  749.         pp->status = MSTART;
  750.         else
  751.         pp->status++;
  752.     else if (pp->status > 0)
  753.         pp->status--;
  754.  
  755.     if (dogfight)
  756.     {
  757.         ptemp = get_indata(1);    /* read all input data        */
  758.         if (ptemp != NULL)
  759.         {
  760.         sprintf(charbuf, "You were blown up by an enemy %s fired by %s",
  761.             WEAPON_NAME[ptemp->mtype], ptemp->myname);
  762.         make_crash(charbuf);
  763.         }
  764.     }
  765.  
  766.     /*
  767.      *  If the plane is not crashed to the ground
  768.      */
  769.     if ((pp->status || !on_ground) && !on_hill)
  770.     {
  771.         if (autopilot_on)
  772.         autopilot();
  773.  
  774.         compute_speeds();
  775.  
  776.         update_position();
  777.  
  778.         test_position();
  779.     }
  780.  
  781.     update_missiles();
  782.  
  783.     draw_scene();
  784.  
  785.     if (dogfight)
  786.         draw_messages();        /* display any network messages    */
  787.  
  788.     /****************************************************************
  789.     /*    compute new velocities, accelerations
  790.     /****************************************************************/
  791.     if (!hud && !new_inst)
  792.         draw_clear_meters();    /* sets up viewport, ortho, wm    */
  793.  
  794.     /*
  795.      *  check my missile against my plane
  796.      */
  797.     if (pp->mstatus && pp->mstatus < MEXPLODE && test_blow_up(pp, pp))
  798.     {
  799.         sprintf(charbuf, "You were blown up by your own %s",
  800.             WEAPON_NAME[pp->mtype]);
  801.         make_crash(charbuf);
  802.         sprintf(charbuf, "blown up by my own %s", WEAPON_NAME[pp->mtype]);
  803.         broadcast(charbuf);
  804.     }
  805.  
  806.     if (pp->mstatus)
  807.         check_missile(pp);    /* first test for missile hit */
  808.  
  809.     if (dogfight)
  810.         send_outdata(pp);    /* send my data out over net */
  811.  
  812.     if (fuel <= 0)        /* out of gas */
  813.     {
  814.         throttle = thrust = pp->thrust = 0;
  815.         max_throttle = 0;
  816.         min_throttle = 0;
  817.     }
  818.  
  819.     do_flight();
  820.  
  821.     /****************************************************************
  822.     /*    display METERS
  823.     /****************************************************************/
  824.     tick_counter--;                /* 7,6,5,4,3,2,1,0 */
  825.  
  826.     if (!pp->mstatus && missile_target)    /* zero target if one */
  827.         if (--missile_target_timeout <= 0)
  828.         missile_target = NULL_PLANE_ID;
  829.  
  830.     if (tick_counter <= 1 && wing_stall && pp->status >= MEXPLODE)
  831.         ringbell();
  832.  
  833.     if (tick_counter & 1)
  834.     {                    /* only do this on odd ticks */
  835.         last_airspeed = airspeed;        /* needed for autopilot */
  836.         last_climbspeed = climbspeed;
  837.         pp->airspeed = airspeed = -(int)(fps_knots * vz);
  838.     }
  839.  
  840.     draw_meters();
  841.  
  842.     if (tick_counter == 0)    /* only update them every second */
  843.     {
  844.         if (flaps && airspeed > 400-flaps)        /* rip off flaps */
  845.         {
  846.         for (itemp=flaps; itemp>0; itemp-=10) qenter(KEYBD, 'F');
  847.         Fmax = 0;
  848.         }
  849.         if (wheels && airspeed > 400)    /* if airspeed > 400 knots */
  850.         {
  851.         qenter(KEYBD, 'l');        /* rip off the gear */
  852.         landing_gear_stuck = 0;
  853.         }
  854.  
  855.         /*
  856.          *  calculate the current tps (ticks per second)
  857.          *  and reset the tick counter
  858.          */
  859.         time_end = times(&tms_end_buf);
  860.         check_time();
  861.         time_start = times(&tms_start_buf);
  862.         tick_counter = int_tps;        /* reset tick counter */
  863.     }
  864.  
  865.     /*
  866.      *  addjust flight characteristics for frame rate change
  867.      */
  868.     vx += vx_add;
  869.     vy += vy_add;
  870.     vz += vz_add;
  871.     missile_vx += missile_vx_add;
  872.     missile_vy += missile_vy_add;
  873.     missile_vz += missile_vz_add;
  874.  
  875.     tps += tps_add;
  876.     pp->tps = tps;
  877.  
  878.     fps_knots = tps * (3600.0/6082.0);
  879.     gravity = G_ACC / tps / tps;
  880.     Lmax_g = Lmax * gravity;
  881.     Lmin_g = Lmin * gravity;
  882.  
  883.     swapbuffers();
  884.  
  885.     }
  886. }
  887.  
  888.  
  889.  
  890. addplane(Plane p)
  891. {
  892.     int i;
  893.     radar_hist_t *rh;
  894.  
  895.     number_planes++;
  896.  
  897.     if (radar)
  898.     {
  899.     for (i=0; i <= number_planes; i++)
  900.         if (radar_history[i].id == NULL_PLANE_ID)
  901.         {
  902.         rh = &radar_history[i];
  903.         rh->id = PLANE_ID(p);
  904.         rh->n = 0;
  905.         reset_radar_hist(rh);
  906.         return;
  907.         }
  908.     }
  909.     else if (!shadow)
  910.     {
  911.     rebuild_status();
  912.     if (dogfight && new_inst)
  913.     {
  914.         sprintf(charbuf, "Players: %d", number_planes);
  915.         set_text_meter(1, charbuf, -1);
  916.     }
  917.     }
  918. }
  919.  
  920.  
  921. delplane(Plane p)
  922. {
  923.     long i, id;
  924.  
  925.     number_planes--;
  926.  
  927.     if (radar)
  928.     {
  929.     id = PLANE_ID(p);
  930.     for (i=0; i < MAX_PLANES; i++)
  931.         if (id == radar_history[i].id)
  932.         {
  933.         radar_history[i].id = NULL_PLANE_ID;
  934.         return(number_planes);
  935.         }
  936.     }
  937.     else if (!shadow)
  938.     {
  939.     rebuild_status();
  940.     if (dogfight && new_inst)
  941.     {
  942.         sprintf(charbuf, "Players: %d", number_planes);
  943.         set_text_meter(1, charbuf, -1);
  944.     }
  945.     }
  946.     return(number_planes);
  947. }
  948.  
  949.  
  950. rebuild_status()
  951. {
  952.     sprintf(status_text, "%s   Rockets:%d  Sidewinders:%d  Players:%d",
  953.         plane_type, rockets, sidewinders, number_planes);
  954. }
  955.  
  956.  
  957. float fuel_consump(thrust, half_mass)
  958.     float thrust, half_mass;
  959. {
  960.     return(test_mode ? 0.0 : 0.3 * thrust/half_mass);
  961. }
  962.  
  963.  
  964. #define CLOCKRATE HZ
  965. #define DY 14
  966.  
  967. check_time()
  968. {
  969.     register int y, s60;
  970.     register char charbuf[80];
  971.     register float veldiff;
  972.     int current_tps, tps_dif;
  973.  
  974.     s60 = time_end - time_start;
  975.     if (s60 <= 0)
  976.     s60 = (tms_end_buf.tms_utime-tms_start_buf.tms_utime) +
  977.           (tms_end_buf.tms_stime-tms_start_buf.tms_stime);
  978.     if (s60 == 0)
  979.     s60 = 1;
  980.  
  981.     current_tps = int_tps * CLOCKRATE / s60;
  982.  
  983.     if (timeit)                /* display the timeing info */
  984.     {
  985.     clear_report();
  986.  
  987.     y = (DY * 3) + 5;
  988.  
  989.     add_report_line(150, 0.80, "Times for main loop:");
  990.  
  991.     sprintf(charbuf, "    %d in %d.%02d seconds",
  992.         int_tps, s60/CLOCKRATE, (s60%CLOCKRATE)*1000/CLOCKRATE/10);
  993.     add_report_line(150, 0.55, charbuf);
  994.  
  995.     sprintf(charbuf, "    %d msecs per call", s60*1000/CLOCKRATE/int_tps);
  996.     add_report_line(150, 0.30, charbuf);
  997.  
  998.     sprintf(charbuf, "    %d per second", current_tps);
  999.     add_report_line(150, 0.05, charbuf);
  1000.  
  1001.     if (!hud && !shadow)
  1002.     {
  1003.         frontbuffer(TRUE);
  1004.         clear_report_area();
  1005.         draw_report();
  1006.         frontbuffer(FALSE);
  1007.     }
  1008.     }
  1009.  
  1010.     tps = int_tps;
  1011.  
  1012.     if (current_tps == int_tps)
  1013.     {
  1014.     vx_add = vy_add = vz_add =
  1015.     missile_vx_add = missile_vy_add = missile_vz_add =
  1016.     tps_add = 0.0;
  1017.     return;
  1018.     }
  1019.     else if (current_tps > int_tps)
  1020.     {
  1021.     tps_dif = (current_tps - int_tps) / 3 + 1;
  1022.     }
  1023.     else /* (current_tps < int_tps) */
  1024.     {
  1025.     tps_dif = (current_tps - int_tps) / 3 - 1;
  1026.     if (int_tps+tps_dif < 3)
  1027.         tps_dif = 3 - int_tps;
  1028.     }
  1029.     veldiff = int_tps / (float)(int_tps + tps_dif);
  1030.     int_tps += tps_dif;
  1031.     tps_add = tps_dif / (float)int_tps;
  1032.  
  1033.     vx_add = ((vx * veldiff) - vx) / int_tps;
  1034.     vy_add = ((vy * veldiff) - vy) / int_tps;
  1035.     vz_add = ((vz * veldiff) - vz) / int_tps;
  1036.     missile_vx_add = ((missile_vx * veldiff) - missile_vx) / int_tps;
  1037.     missile_vy_add = ((missile_vy * veldiff) - missile_vy) / int_tps;
  1038.     missile_vz_add = ((missile_vz * veldiff) - missile_vz) / int_tps;
  1039. }
  1040.  
  1041.  
  1042. check_dials()
  1043. /* Check the dial and button box, and load the apropriate value onto
  1044.  * the cue.  The dials are as follows:
  1045.  *
  1046.  *    DIAL0 = Thrust up/down.
  1047.  *    DIAL1 = Flaps up/down.
  1048.  *    DIAL2 = Spoilers up/down.
  1049.  *    DIAL4 = Tower veiw in/out.    */
  1050. {
  1051.  
  1052.     long value;
  1053.     int i;
  1054.  
  1055.     /* Check for thrust */
  1056.     value = getvaluator(DIAL0) - 200;
  1057.     if (value <= -10)
  1058.     {
  1059.     setvaluator(DIAL0, 200, 0, 400);
  1060.     for (i = 0 ; i >= (value/10) ; i--)
  1061.         qenter(KEYBD, 'a');
  1062.     }
  1063.     if (value >= 10)
  1064.     {
  1065.     setvaluator(DIAL0, 200, 0, 400);
  1066.     for (i = 0 ; i <= (value/10) ; i++)
  1067.         qenter(KEYBD, 's');
  1068.     }
  1069.  
  1070.     /* Check for flaps */
  1071.     value = getvaluator(DIAL1) - 50;
  1072.     if (value <= -10)
  1073.     {
  1074.     setvaluator(DIAL1, 50, 0, 100);
  1075.     for (i = 0 ; i >= (value/10) ; i--)
  1076.         qenter(KEYBD, 'F');
  1077.     }
  1078.     if (value >= 10)
  1079.     {
  1080.     setvaluator(DIAL1, 50, 0, 100);
  1081.     for (i = 0 ; i <= (value/10) ; i++)
  1082.         qenter(KEYBD, 'f');
  1083.     }
  1084.  
  1085.     /* Check the spoilers */
  1086.     value = getvaluator(DIAL2) - 30;
  1087.     if (value <= -10)
  1088.     {
  1089.     setvaluator(DIAL2, 30, 0, 60);
  1090.     for (i = 0 ; i >= (value/10) ; i--)
  1091.         qenter(KEYBD, 'C');
  1092.     }
  1093.     if (value >= 10)
  1094.     {
  1095.     setvaluator(DIAL2, 30, 0, 60);
  1096.     for (i = 0 ; i <= (value/10) ; i++)
  1097.         qenter(KEYBD, 'c');
  1098.     }
  1099.  
  1100.     /* Check the tower view */
  1101.     value = getvaluator(DIAL4) - 240;
  1102.     if (value <= -10)
  1103.     {
  1104.     setvaluator(DIAL4, 240, 0, 480);
  1105.     for (i = 0 ; i >= (value/10) ; i--)
  1106.         qenter(KEYBD, 'z');
  1107.     }
  1108.     if (value >= 10)
  1109.     {
  1110.     setvaluator(DIAL4, 240, 0, 480);
  1111.     for (i = 0 ; i <= (value/10) ; i++)
  1112.         qenter(KEYBD, 'x');
  1113.     }
  1114. }
  1115.  
  1116.  
  1117. /*
  1118.  *  Initialize the dials to the correct values
  1119.  */
  1120. init_dials()
  1121. {
  1122.     setvaluator(DIAL0, 200, 0, 400);
  1123.     setvaluator(DIAL1, 50, 0, 100);
  1124.     setvaluator(DIAL2, 30, 0, 60);
  1125.     setvaluator(DIAL4, 240, 0, 480);
  1126. }
  1127.  
  1128.  
  1129. #define TEST_EVENT        \
  1130.     if (event_break && qtest())    \
  1131.     return            \
  1132.  
  1133.  
  1134. /*
  1135.  *  read_objects() reads the data files needed by flight.  It is designed
  1136.  *  to be run several times.  If event break is set it will check after
  1137.  *  each data file read for events pending in the queue.  If it find
  1138.  *  events it will abort.
  1139.  */
  1140. read_objects(event_break)
  1141.     int event_break;
  1142. {
  1143.     static int objects_to_read = TRUE;
  1144.     int i;
  1145.  
  1146.     if (!objects_to_read)
  1147.     return;
  1148.  
  1149.     if (!event_break)
  1150.     display_wait();
  1151.  
  1152.     /*
  1153.      *  read object files
  1154.      */
  1155.  
  1156.     if (!runwayobj)
  1157.     {
  1158.     strcpy(objfname, objdir);
  1159.     strcat(objfname, "runway.d");
  1160.     runwayobj = readobj(objfname);
  1161.     if (in_cmode && bits_cmode < 6)
  1162.         remap_obj(runwayobj);
  1163.     }
  1164.  
  1165.     TEST_EVENT;
  1166.  
  1167.     if (!lightsobj)
  1168.     {
  1169.     strcpy(objfname, objdir);
  1170.     strcat(objfname, "lights.d");
  1171.     lightsobj = readobj(objfname);
  1172.     if (in_cmode && bits_cmode < 6)
  1173.         remap_obj(lightsobj);
  1174.     }
  1175.  
  1176.     TEST_EVENT;
  1177.  
  1178.     if (!planeobj[C150])
  1179.     {
  1180.     strcpy(objfname, objdir);
  1181.     strcat(objfname, "c150.d");
  1182.     planeobj[C150] = readobj(objfname);
  1183.     if (in_cmode && bits_cmode < 6)
  1184.         remap_obj(planeobj[C150]);
  1185.     }
  1186.  
  1187.     TEST_EVENT;
  1188.  
  1189.     if (!planeobj[F16])
  1190.     {
  1191.     strcpy(objfname, objdir);
  1192.     strcat(objfname, "f16.d");
  1193.     planeobj[F16] = readobj(objfname);
  1194.     if (in_cmode && bits_cmode < 6)
  1195.         remap_obj(planeobj[F16]);
  1196.     }
  1197.  
  1198.     TEST_EVENT;
  1199.  
  1200.     if (!planeobj[F18])
  1201.     {
  1202.     strcpy(objfname, objdir);
  1203.     strcat(objfname, "f18.d");
  1204.     planeobj[F18] = readobj(objfname);
  1205.     if (in_cmode && bits_cmode < 6)
  1206.         remap_obj(planeobj[F18]);
  1207.     }
  1208.  
  1209.     TEST_EVENT;
  1210.  
  1211.     if (!planeobj[B747])
  1212.     {
  1213.     strcpy(objfname, objdir);
  1214.     strcat(objfname, "b747.d");
  1215.     planeobj[B747] = readobj(objfname);
  1216.     if (in_cmode && bits_cmode < 6)
  1217.         remap_obj(planeobj[B747]);
  1218.     }
  1219.  
  1220.     TEST_EVENT;
  1221.  
  1222.     if (!planeobj[B727])
  1223.     {
  1224.     if (!in_cmode)
  1225.     {
  1226.         strcpy(objfname, objdir);
  1227.         strcat(objfname, "b727.d");        /* in_cmode uses 747 instead */
  1228.     }
  1229.     planeobj[B727] = readobj(objfname);
  1230.     if (in_cmode && bits_cmode < 6)
  1231.         remap_obj(planeobj[B727]);
  1232.     }
  1233.  
  1234.     TEST_EVENT;
  1235.  
  1236.     if (!planeobj[P38])
  1237.     {
  1238.     strcpy(objfname, objdir);
  1239.     strcat(objfname, "p38.d");
  1240.     planeobj[P38] = readobj(objfname);
  1241.     if (in_cmode && bits_cmode < 6)
  1242.         remap_obj(planeobj[P38]);
  1243.     }
  1244.  
  1245.     TEST_EVENT;
  1246.  
  1247.     if (!planeobj[F14])
  1248.     {
  1249.     strcpy(objfname, objdir);
  1250.     strcat(objfname, "f14.d");
  1251.     planeobj[F14] = readobj(objfname);
  1252.     if (in_cmode && bits_cmode < 6)
  1253.         remap_obj(planeobj[F14]);
  1254.     }
  1255.  
  1256.     TEST_EVENT;
  1257.  
  1258.     if (!planeobj[F15])
  1259.     {
  1260.     if (in_cmode)
  1261.     {
  1262.         strcpy(objfname, objdir);
  1263.         strcat(objfname, "f15.d");        /* RGBmode uses F14 instead */
  1264.     }
  1265.     planeobj[F15] = readobj(objfname);
  1266.     if (in_cmode && bits_cmode < 6)
  1267.         remap_obj(planeobj[F15]);
  1268.     if (!in_cmode)
  1269.     {
  1270.         setrotation(planeobj[F15], 2, -480, 'y');
  1271.         setrotation(planeobj[F15], 3, 480, 'y');
  1272.     }
  1273.     }
  1274.  
  1275. #if 0
  1276.     TEST_EVENT;
  1277.  
  1278.     if (!planeobj[STEALTH])
  1279.     {
  1280.     strcpy(objfname, objdir);
  1281.     strcat(objfname, "stealth.d");
  1282.     planeobj[STEALTH] = readobj(objfname);
  1283.     }
  1284. #endif
  1285.  
  1286.     TEST_EVENT;
  1287.  
  1288.     if (!buildingsobj)
  1289.     {
  1290.     if (in_cmode)
  1291.     {
  1292.         for (i = 0; i < NUM_BUILDINGS; i++)
  1293.         {
  1294.         float x, y, z;
  1295.  
  1296.         sprintf(objfname, "%sbci%d.d", objdir, i);
  1297.         buildingsobj = readobj(objfname);
  1298.         avg_verts(buildingsobj, &x, &y, &z);
  1299.         if (bits_cmode < 6)
  1300.             remap_obj(buildingsobj);
  1301.  
  1302.         add_obj(BUILDING_OBJ, x, y, z, buildingsobj);
  1303.         }
  1304.     }
  1305.     else
  1306.     {
  1307.         strcpy(objfname, objdir);
  1308.         strcat(objfname, "buildings.d");
  1309.         buildingsobj = readobj(objfname);
  1310.     }
  1311.     }
  1312.  
  1313.     TEST_EVENT;
  1314.  
  1315.     if (!mtnsobj)
  1316.     {
  1317.     strcpy(objfname, objdir);
  1318.     strcat(objfname, "mtns.d");
  1319.     mtnsobj = readobj(objfname);
  1320.     if (in_cmode && bits_cmode < 6)
  1321.         remap_obj(mtnsobj);
  1322.     }
  1323.  
  1324.     TEST_EVENT;
  1325.  
  1326.     if (!swobj)
  1327.     {
  1328.     strcpy(objfname, objdir);
  1329.     strcat(objfname, "sw.d");
  1330.     swobj = readobj(objfname);
  1331.     if (in_cmode && bits_cmode < 6)
  1332.         remap_obj(swobj);
  1333.     }
  1334.  
  1335.     TEST_EVENT;
  1336.  
  1337.     if (!threatobj)
  1338.     {
  1339.     strcpy(objfname, objdir);
  1340.     strcat(objfname, "threat.d");
  1341.     if (in_cmode)
  1342.     {
  1343.         threatobj = readobj(objfname);
  1344.         settranslation(threatobj, 0, 6000.0, 0.0, 14000.0);
  1345.         setscale(threatobj, 1, 17000.0, 17000.0, 17000.0);
  1346.         if (bits_cmode < 6)
  1347.         remap_obj(threatobj);
  1348.         add_obj(THREAT_OBJ, 6000.0, 0.0, 14000.0, threatobj);
  1349.  
  1350.         threatobj = readobj(objfname);
  1351.         settranslation(threatobj, 0, -20000.0, 0.0, 15000.0);
  1352.         setscale(threatobj, 1, 10700.0, 10700.0, 10700.0);
  1353.         if (bits_cmode < 6)
  1354.         remap_obj(threatobj);
  1355.         add_obj(THREAT_OBJ, -20000.0, 0.0, 15000.0, threatobj);
  1356.  
  1357.         threatobj = readobj(objfname);
  1358.         settranslation(threatobj, 0, 3000.0, 0.0, 34000.0);
  1359.         setscale(threatobj, 1, 2700.0, 2700.0, 2700.0);
  1360.         if (bits_cmode < 6)
  1361.         remap_obj(threatobj);
  1362.         add_obj(THREAT_OBJ, 3000.0, 0.0, 34000.0, threatobj);
  1363.     }
  1364.     else
  1365.     {
  1366.         threatobj = readobj(objfname);
  1367.     }
  1368.     }
  1369.  
  1370.     TEST_EVENT;
  1371.  
  1372.     if (!hillsobj && !in_cmode)
  1373.     {
  1374.     strcpy(objfname, objdir);
  1375.     strcat(objfname, "hills.d");
  1376.     hillsobj = readobj(objfname);
  1377.     strcpy(objfname, datadir);
  1378.     strcat(objfname, "hills.grid");
  1379.     hillsgrid = read_grid(objfname);
  1380.     }
  1381.  
  1382.     if (in_cmode)
  1383.     {
  1384.     for (i = 0; i < MAX_PLANES; i++)
  1385.     {
  1386.         sort_plane[i].type = PLANE_OBJ;
  1387.         sort_plane[i].id = i;
  1388.         sort_missile[i].type = MISSILE_OBJ;
  1389.         sort_missile[i].id = i;
  1390.     }
  1391.     }
  1392.  
  1393.     objects_to_read = FALSE;
  1394. }
  1395.  
  1396.  
  1397. /*
  1398.  *  stopit() will iconify flight and get it up and running again when the user
  1399.  *  restarts it.
  1400.  */
  1401. stopit()
  1402. {
  1403. #ifdef FIX_XXX
  1404.     extern PSFILE *PostScript;
  1405.     short dummy;
  1406.  
  1407.     /*
  1408.      *  do most of same stuff as when we exit in ExitComm()
  1409.      */
  1410.     restore_map();
  1411.  
  1412.     /*
  1413.      *  clear the pup underlay and color planes
  1414.      */
  1415.     viewport(0, xmaxwindow, 0, ymaxwindow);
  1416.     drawmode(PUPDRAW);
  1417.     color(0);
  1418.     clear();
  1419.     drawmode(UNDERDRAW);
  1420.     color(0);
  1421.     clear();
  1422.     drawmode(NORMALDRAW);
  1423.     frontbuffer(TRUE);
  1424.     cpack(0);
  1425.     clear();
  1426.     frontbuffer(FALSE);
  1427.  
  1428.     /*
  1429.      *    flight will iconify and suspend apon flipiconic().  The code following
  1430.      *  flipiconic will get flight up and running again.
  1431.      */
  1432.     flipiconic(winget());
  1433.     winpop();    /* This is a kludge to keep flight from continuing before */
  1434.         /* iconifying */
  1435.  
  1436.     while (qread(&dummy) != REDRAW);    /* will hang here until uniconified */
  1437.  
  1438.     winpop();    /* This is a kludge to keep flight from continuing before */
  1439.         /* its window id bits have been painted */
  1440.  
  1441.     if (dogfight)
  1442.     init_graphics("dog");
  1443.     else
  1444.     init_graphics("flight");
  1445.  
  1446.     if (dials) init_dials();
  1447.  
  1448.     /*
  1449.      *  restore mouse position
  1450.      */
  1451.     setvaluator(MOUSEX, mousex, 0, xmaxscreen);
  1452.     setvaluator(MOUSEY, mousey, 0, ymaxscreen);
  1453.  
  1454.     winpop();    /* make sure at top! */
  1455.     redraw_screen();
  1456. #endif
  1457. }
  1458.  
  1459.  
  1460. /*
  1461.  *  read all queue entries
  1462.  */
  1463. read_queue()
  1464. {
  1465.     short type, val;
  1466.     float temp;
  1467.     Plane pp = planes[0], ptemp;
  1468.  
  1469.     while (qtest())
  1470.     {
  1471.     switch (type = qread(&val))
  1472.     {
  1473.         case KEYBD:
  1474.         switch (val)
  1475.         {
  1476.             case 27:
  1477.             end_of_program();
  1478.             case 'b':
  1479.             bell = !bell;
  1480.             setbell(bell);
  1481.             break;
  1482.             case 'a':
  1483.             throttle -= 5;
  1484.             if (throttle < min_throttle)
  1485.                 throttle = min_throttle;
  1486.             break;
  1487.             case 's':
  1488.             throttle += 5;
  1489.             if (throttle > max_throttle)
  1490.                 throttle = max_throttle;
  1491.             break;
  1492. #ifdef AUDIO
  1493.             case 'S':
  1494.             if (--sound_mode < 0) sound_mode = 2;
  1495.             break;
  1496. #endif
  1497.             case 'z':
  1498.             case 'x':
  1499.             if (view_switch == TOWER_VIEW)
  1500.             {
  1501.                 if (val == 'x')
  1502.                 {
  1503.                 if (tower_fov > 30) tower_fov -= 25;
  1504.                 }
  1505.                 else
  1506.                 {
  1507.                 if (tower_fov < 600) tower_fov += 25;
  1508.                 }
  1509.                 reset_fov(tower_fov);
  1510.             }
  1511.             else if (missile_view)
  1512.             {
  1513.                 if (val == 'x')
  1514.                 {
  1515.                 if (mvfollow > 0) mvfollow--;
  1516.                 }
  1517.                 else
  1518.                 if (mvfollow < 9) mvfollow++;
  1519.             }
  1520.             else if (wingman_view)
  1521.             {
  1522.                 if (val == 'x')
  1523.                 {
  1524.                 if (wmfollow > 0) wmfollow--;
  1525.                 }
  1526.                 else
  1527.                 if (wmfollow < 9) wmfollow++;
  1528.             }
  1529.             break;
  1530.             case 'd':
  1531.             if (view_switch != TOWER_VIEW)
  1532.             {
  1533.                 view_switch = TOWER_VIEW;
  1534.                 eye_x = TOWER_X;
  1535.                 eye_y = TOWER_Y;
  1536.                 eye_z = TOWER_Z;
  1537.                 reset_fov(tower_fov);
  1538.             }
  1539.             else
  1540.             {
  1541.                 view_switch = PLANE_VIEW;
  1542.                 reset_fov(plane_fov);
  1543.             }
  1544.             break;
  1545.             case 'Q':
  1546.             missile_view = !missile_view;
  1547.             break;
  1548.             case 'W':
  1549.             wingman_view = !wingman_view;
  1550.             break;
  1551.             case '-':
  1552.             cam_dist -= 15.0;
  1553.             break;
  1554.             case '=':
  1555.             cam_dist += 15.0;
  1556.             break;
  1557.             case 'v':
  1558.             autopilot_on = !autopilot_on;
  1559.             if (autopilot_on)
  1560.             {
  1561.                 target_speed = airspeed;
  1562.                 target_climb = climbspeed;
  1563.                 target_twist = twist;
  1564.             }
  1565.             break;
  1566.             case 'f':
  1567.             case 'F':
  1568.             if (val == 'f')
  1569.             {
  1570.                 if (flaps < Fmax) flaps += 10;
  1571.             }
  1572.             else
  1573.             {
  1574.                 if (flaps > 0) flaps -= 10;
  1575.             }
  1576.             max_cl = 1.5 + flaps/62.5;
  1577.             min_cl = flaps/62.5 - 1.5;
  1578.             tilt_factor = .005 * flaps + .017;
  1579.             break;
  1580.             case 'c':
  1581.             case 'C':
  1582.             if (val == 'c')
  1583.             {
  1584.                 if (spoilers < Smax) spoilers += 20;
  1585.             }
  1586.             else
  1587.             {
  1588.                 if (spoilers > 0) spoilers -= 20;
  1589.             }
  1590.             Spdf = .0025 * spoilers;    /* adjust drag and lift */
  1591.             Splf = 1.0 - .005 * spoilers;
  1592.             break;
  1593.             case 'l':
  1594.             if (landing_gear_stuck != wheels)
  1595.             {
  1596.                 if (wheels)
  1597.                 {
  1598.                 wheels = FALSE;
  1599.                 Cdp /= 2.0;
  1600.                 wheels_retracting = 1;
  1601.                 if (on_ground && pp->status > MEXPLODE)
  1602.                 {
  1603. make_crash("You retracted the landing gear while on the ground");
  1604. broadcast("retracted my landing gear while on the ground");
  1605.                 }
  1606.                 }
  1607.                 else
  1608.                 {
  1609.                 wheels = TRUE;
  1610.                 wheels_retracting = -1;
  1611.                 Cdp *= 2.0;
  1612.                 }
  1613.             }
  1614.             break;
  1615.             case 't':
  1616.             /* if I'm alive and no weapon already fired */
  1617.             if (pp->status > MEXPLODE && !pp->mstatus)
  1618.             {
  1619.                 if (ptemp = find_closest_plane(pp))
  1620.                 {
  1621.                 /* lock on the plane for 1 second */
  1622. #ifdef AUDIO
  1623.                 play_samps( locksample, locklength);
  1624. #endif
  1625.                 missile_target = PLANE_ID(ptemp);
  1626.                 missile_target_timeout = int_tps;
  1627.                 if (ptemp)
  1628.                 {
  1629.                     sprintf(charbuf, "Locked on->%s",
  1630.                         ptemp->myname);
  1631.                     set_text_meter(0, charbuf, int_tps);
  1632.                 }
  1633.                 }
  1634.             }
  1635.             break;
  1636.             case 'q':
  1637.             launch_missile(TYPE_ROCKET);
  1638.             break;
  1639.             case 'w':
  1640.             launch_missile(TYPE_SIDEWINDER);
  1641.             break;
  1642.             case 'e':
  1643.             launch_missile(TYPE_CANNON);
  1644.             break;
  1645.             case 'm':
  1646.             set_fog_density(-1);
  1647.             break;
  1648.             case 'M':
  1649.             set_fog_density(1);
  1650.             break;
  1651.             case 'n':
  1652.             set_ftime(ftime + 5);
  1653.             break;
  1654.             case 'N':
  1655.             set_ftime(ftime - 5);
  1656.             break;
  1657.             case 'h':
  1658.             show_help = !show_help;
  1659.             break;
  1660.             case 'H':
  1661.             /*
  1662.              *  switch from hud to instrument panel
  1663.              */
  1664.             hud = !hud;
  1665.             redraw_screen();
  1666.             if (!hud)
  1667.             {
  1668.                 clear_report_card();
  1669.                 plane_fov = 360;
  1670.                 dist_for_lines >>= 1;
  1671.             }
  1672.             else
  1673.             {
  1674.                 plane_fov = 400;
  1675.                 dist_for_lines <<= 1;
  1676.             }
  1677.             if (view_switch == TOWER_VIEW)
  1678.                 reset_fov(tower_fov);
  1679.             else
  1680.                 reset_fov(plane_fov);
  1681.             break;
  1682.             case 'r':
  1683.             case 'R':
  1684.             case 'u':
  1685.             case 'U':
  1686.             if (pp->status == 0)
  1687.                 if      (val == 'r')    restart = START1;
  1688.                 else if (val == 'R')    restart = START2;
  1689.                 else if (val == 'u')    restart = START3;
  1690.                 else /* (val == 'U') */ restart = START4;
  1691.             else
  1692.                 /*
  1693.                  *  if missile launched, then blow it up
  1694.                  */
  1695.                 if (pp->mstatus > MEXPLODE &&
  1696.                 (pp->mtype == TYPE_ROCKET ||
  1697.                  pp->mtype == TYPE_SIDEWINDER))
  1698.                 pp->mstatus = MEXPLODE;
  1699.             break;
  1700.             case 'T':
  1701.             threat_mode = !threat_mode;
  1702.             break;
  1703.             case 'I':    /* iconize and suspend */
  1704.             stopit();
  1705.             break;
  1706.             case '~':
  1707.             test_mode = !test_mode;
  1708.             fuel_rate = fuel_consump(Mthrust, W);
  1709.             sidewinders = rockets = 0;
  1710.             rebuild_status();
  1711.             break;
  1712.             case '?':
  1713.             timeit = !timeit;
  1714.             break;
  1715.             case '':
  1716.             wait_for_input();
  1717.             break;
  1718. #ifdef DEBUG
  1719.             case '-':
  1720.             case '_':
  1721.             if (dogfight)
  1722.                 rewind_if(-10);
  1723.             break;
  1724.             case '+':
  1725.             case '=':
  1726.             if (dogfight)
  1727.                 rewind_if(10);
  1728.             break;
  1729.             case '':
  1730.             view_switch = -view_switch;
  1731.             break;
  1732.             case 'P':
  1733.             wait_for_input();
  1734.             break;
  1735.             default:
  1736.             if (val >= '0' && val <= '9')
  1737.             debug ^= 1 << (val-'0');
  1738. #endif
  1739.         }
  1740.         break;
  1741.         case MOUSEX:
  1742.         mousex = val;
  1743.         break;
  1744.         case MOUSEY:
  1745.         mousey = val;
  1746.         break;
  1747.         case SBTX:
  1748.         sbtx = val;
  1749.         break;
  1750.         case SBTZ:
  1751.         sbtz = val;
  1752.         break;
  1753.         case F1KEY:        /* toggle fog */
  1754.         if (val)
  1755.             fogit = !fogit && !in_cmode && (getgdesc(GD_FOGVERTEX) > 0);
  1756.         break;
  1757.         case F2KEY:        /* toggle texturing */
  1758.         if (val)
  1759.             texit = !texit && !in_cmode && (getgdesc(GD_TEXTURE) > 0);
  1760.         break;
  1761.         case REDRAW:
  1762.         redraw_screen();
  1763.         break;
  1764.         case WINQUIT:
  1765.         end_of_program();
  1766.         break;
  1767.         case MOUSE3:
  1768.         case SBBUT6:
  1769.         if (val)
  1770.             if (rudder > -.75)
  1771.             rudder -= .1;
  1772.         break;
  1773.         case MOUSE2:
  1774.         case SBBUT7:
  1775.         if (val)
  1776.             rudder = 0;
  1777.         break;
  1778.         case MOUSE1:
  1779.         case SBBUT8:
  1780.         if (val)
  1781.             if (rudder < .75)
  1782.             rudder += .1;
  1783.         break;
  1784.         case SBPICK:
  1785.         launch_missile(TYPE_CANNON);
  1786.         break;
  1787.         case SBBUT2:
  1788.         launch_missile(TYPE_ROCKET);
  1789.         break;
  1790.         case SBBUT3:
  1791.         launch_missile(TYPE_SIDEWINDER);
  1792.         break;
  1793.         case LEFTARROWKEY:
  1794.         if (val &&(view_switch==PLANE_VIEW))
  1795.         {
  1796.             view_angle -= 50;
  1797.             if (view_angle <= -1800)
  1798.             view_angle += 3600;
  1799.         }
  1800.         break;
  1801.         case RIGHTARROWKEY:
  1802.         if (val && (view_switch == PLANE_VIEW))
  1803.         {
  1804.             view_angle += 50;
  1805.             if (view_angle > 1800)
  1806.             view_angle -= 3600;
  1807.         }
  1808.         break;
  1809.         case UPARROWKEY:
  1810.         if (val && (view_switch == PLANE_VIEW))
  1811.             view_angle = 0;
  1812.         break;
  1813.         case DOWNARROWKEY:
  1814.         if (val && (view_switch == PLANE_VIEW))
  1815.             view_angle = 1800;
  1816.         break;
  1817.         default:
  1818.         break;
  1819.     }    /* of switch qread */
  1820.     }        /* of while qtest */
  1821. }
  1822.  
  1823.  
  1824. /*
  1825.  *  auto pilot routine
  1826.  */
  1827. autopilot()
  1828. {
  1829.     int itemp, diff;
  1830.     Plane pp = planes[0];
  1831.  
  1832.     itemp = mousey;
  1833.     /* first adjust the roll ??? XXX    */
  1834.  
  1835.     /*
  1836.      *  adjust speed next
  1837.      */
  1838.     diff = target_speed - airspeed - ((airspeed-last_airspeed)<<3);
  1839.     diff = (diff+4) >> 3;
  1840.     if (diff > 0)        /* need more acceleration    */
  1841.     {
  1842.     if (throttle < max_throttle)
  1843.         throttle += diff;        /* try engines first */
  1844.     else if (!on_ground)
  1845.     {                /* next wheels and yaw    */
  1846.         if (flaps && vz < -400.0/TPS)
  1847.         qenter(KEYBD, 'F');
  1848.         else if (rudder > 0.05)
  1849.         rudder -= .1;
  1850.         else if (rudder < -0.05)
  1851.         rudder += .1;
  1852.         else
  1853.         setvaluator(MOUSEY,    /* lastly pitch        */
  1854.                mousey = (itemp+=(int)(diff/-ELEVF/vz)),
  1855.                0, ymaxscreen);
  1856.     }
  1857.     }
  1858.     else if (diff < 0)        /* need less acceleration    */
  1859.     {
  1860.     throttle += diff;        /* reduce thrust        */
  1861.     if (throttle < min_throttle)
  1862.         throttle = min_throttle;
  1863.     }
  1864.  
  1865.     /*
  1866.      *  adjust climb last - this has highest priority
  1867.      */
  1868.     diff = target_climb - climbspeed -
  1869.        ((climbspeed-last_climbspeed) << 7);
  1870.     diff = (diff+4) >> 4;
  1871.  
  1872.     if (wing_stall)
  1873.     {
  1874.     if (throttle < max_throttle)
  1875.         throttle += 10;
  1876.     if (spoilers)
  1877.         qenter(KEYBD, 'C');
  1878.     }
  1879.     else if (diff != 0)
  1880.     {
  1881.     if (twist > 900 && twist < 2700)
  1882.         diff = -diff;
  1883.     setvaluator(MOUSEY, mousey = (itemp+=(int)(diff/ELEVF/vz)),
  1884.             0, ymaxscreen);
  1885.     }
  1886.     if (throttle > max_throttle)
  1887.     throttle = max_throttle;
  1888. }
  1889.  
  1890.  
  1891. #define TDELAY (TPS/4) /*XXX*/
  1892.  
  1893. /*
  1894.  *  compute roll_speed, elevation_speed, azimuth_speed and
  1895.  *  wing stall
  1896.  */
  1897. compute_speeds()
  1898. {
  1899.     int itemp;
  1900.     float temp;
  1901.     Plane pp = planes[0];
  1902.     short tmpx, tmpy;
  1903.     int centered;        /* is the spaceball centered */
  1904.     static int still = TRUE;    /* is the spaceball in use */
  1905.  
  1906.     /*
  1907.      *  check if spaceball is in use
  1908.      */
  1909.     tmpx = sbtx;
  1910.     tmpy = sbtz;
  1911.  
  1912.     centered = !(tmpx || tmpy);
  1913.  
  1914.     if (!centered || !still)
  1915.     {
  1916.     still = centered;
  1917.  
  1918.     tmpx = ((tmpx * xmiddle) >> 13) + xmiddle;
  1919.     tmpy = ((tmpy * ymiddle) >> 13) + ymiddle;
  1920.     if (tmpx > xmaxscreen) tmpx = xmaxscreen;
  1921.     else if (tmpx < 0) tmpx = 0;
  1922.     if (tmpy > ymaxscreen) tmpy = ymaxscreen;
  1923.     else if (tmpy < 0) tmpy = 0;
  1924.  
  1925.     if (pp->status <= MEXPLODE)
  1926.     {
  1927.         sb_xadd += flight_random(20);
  1928.         tmpx += sb_xadd;
  1929.         sb_yadd += flight_random(20);
  1930.         tmpy += sb_yadd;
  1931.     }
  1932.  
  1933.     setvaluator(MOUSEX, mousex = tmpx, 0, xmaxscreen);
  1934.     setvaluator(MOUSEY, mousey = tmpy, 0, ymaxscreen);
  1935.     }
  1936.  
  1937.     /*
  1938.      *  start calculations
  1939.      */
  1940.     /* tenths of degrees per tick    */
  1941.     pp->rollers = mousex;
  1942.     if (pp->status <= MEXPLODE)
  1943.     {
  1944.     pp->rollers += stick_xadd + flight_random(20);
  1945.     setvaluator(MOUSEX, mousex = pp->rollers, 0, xmaxscreen);
  1946.     }
  1947.     pp->rollers -= xmiddle - 8;
  1948.     rollers = ROLLF * (pp->rollers >> 4);
  1949.     itemp = rollers * vz - roll_speed;    /* delta    */
  1950.     if (itemp!=0)
  1951.     if (itemp >= TDELAY || itemp <= -TDELAY)
  1952.         itemp /= TDELAY;
  1953.     else
  1954.         itemp = itemp>0 ? 1 : -1;
  1955.     if (wing_stall > 0)
  1956.     {
  1957.     itemp >>= wing_stall;
  1958.     itemp += flight_random(wing_stall << 3);
  1959.     }
  1960.     roll_speed += itemp;
  1961.  
  1962.     pp->elevator = mousey;
  1963.     if (pp->status <= MEXPLODE)
  1964.     {
  1965.     pp->elevator += stick_yadd + flight_random(20);
  1966.     setvaluator(MOUSEY, mousey = pp->elevator, 0, ymaxscreen);
  1967.     }
  1968.     pp->elevator -= ymiddle - 8;
  1969.     elevator = ELEVF * (pp->elevator >> 4);
  1970.     itemp = elevator * vz + vy - elevation_speed;
  1971.     if (itemp!=0)
  1972.     if (itemp >= TDELAY || itemp <= -TDELAY)
  1973.         itemp /= TDELAY;
  1974.     else
  1975.         itemp = itemp>0 ? 1 : -1;
  1976.     if (wing_stall > 0)
  1977.     {
  1978.     itemp >>= wing_stall;
  1979.     itemp += flight_random(wing_stall << 1);
  1980.     }
  1981.     elevation_speed += itemp;
  1982.  
  1983.     temp = rudder * vz - 2.0 * vx;
  1984.     if (on_ground)
  1985.     {
  1986. #define MAX_TURNRATE (600/TPS) /*XXX*/
  1987.     itemp = 16.0 * temp;
  1988.     if (itemp < -MAX_TURNRATE || itemp > MAX_TURNRATE)
  1989.     {
  1990.         if (itemp < 0)        /* clip turn rate    */
  1991.         itemp = -MAX_TURNRATE;
  1992.         else
  1993.         itemp = MAX_TURNRATE;
  1994.         if (fabs(vz) > 10.0/TPS)    /* decrease with velocity */
  1995.         {
  1996.         temp = 0.4 * TPS * (rudder*vz - .75); /* skid effect */
  1997.         if (temp < -MAX_TURNRATE || temp > MAX_TURNRATE)
  1998.             temp = itemp;
  1999.         itemp -= temp;
  2000.         }
  2001.     }
  2002.     }
  2003.     else
  2004.     itemp = temp;    /* itemp is desired azimuth speed    */
  2005.     itemp -= azimuth_speed;    /* itemp is now desired-actual        */
  2006.  
  2007.     if (itemp!=0)
  2008.     if (itemp >= TDELAY || itemp <= -TDELAY)
  2009.         itemp /= TDELAY;
  2010.     else
  2011.         itemp = itemp>0 ? 1 : -1;
  2012.     azimuth_speed += itemp;
  2013.  
  2014.     if (on_ground)
  2015.     {
  2016.     /*
  2017.      * dont allow negative pitch unless positive elevation
  2018.      */
  2019.     if (elevation_speed < 0)
  2020.     {
  2021.         if (elevation <= 0)
  2022.         elevation_speed = 0;
  2023.     }
  2024.     else        /* mimic gravitational torque    */
  2025.     {
  2026.         itemp = -((int)vz * int_tps + MIN_LIFT_SPEED) >> 2;
  2027.         if (itemp < 0 && elevation <= 0)
  2028.         itemp = 0;
  2029.         if (elevation_speed > itemp)
  2030.         elevation_speed = itemp;
  2031.     }
  2032.     roll_speed = 0;
  2033.     }
  2034. }
  2035.  
  2036.  
  2037. /*
  2038.  *  update_position() updates the vehicles position, azimuth, elevation,
  2039.  *  twist, and velocity.  Based on it's velocity and rotational speeds
  2040.  */
  2041. update_position()
  2042. {
  2043.     float elev_rad;    /* elevation in radians */
  2044.     float cos_elev;    /* cosine of elevation */
  2045.     float temp;
  2046.     register Matrix incremental;    /* temp matrix    */
  2047.     Plane pp = planes[0];
  2048.     float vscale;
  2049.  
  2050.     /*
  2051.      *    concat incremental rotations and get new angles back
  2052.      */
  2053.     identify_matrix(ptw);
  2054.     matrix_translate(ptw, pp->x, pp->y, pp->z);
  2055.     matrix_rotate(ptw, azimuth, 'y');
  2056.     matrix_rotate(ptw, elevation, 'x');
  2057.     matrix_rotate(ptw, twist, 'z');
  2058.  
  2059.     if (pp->status > MEXPLODE || !on_ground)
  2060.     {
  2061.     matrix_translate(ptw, vx, vy, vz);
  2062.     if (azimuth_speed) matrix_rotate(ptw, azimuth_speed, 'y');
  2063.     if (elevation_speed) matrix_rotate(ptw, elevation_speed, 'x');
  2064.     if (roll_speed) matrix_rotate(ptw, roll_speed, 'z');
  2065.     }
  2066.     else
  2067.     {
  2068.     vscale = pp->status / 20.0;
  2069.     matrix_translate(ptw, vx*vscale, vy*vscale, vz*vscale);
  2070.     if (azimuth_speed) matrix_rotate(ptw, azimuth_speed*vscale, 'y');
  2071.     if (elevation_speed) matrix_rotate(ptw, elevation_speed*vscale, 'x');
  2072.     if (roll_speed) matrix_rotate(ptw, roll_speed*vscale, 'z');
  2073.     }
  2074.  
  2075.     /*
  2076.      *  analyze new ptw
  2077.      */
  2078.     elev_rad = -fasin(ptw[2][1]);
  2079.     temp = elev_rad * (1800.0/M_PI);
  2080.     /*
  2081.     temp = -xasin(ptw[2][1]);
  2082.     */
  2083.     elevation = (temp < 0)? temp-0.5: temp + 0.5;
  2084.     cos_elev = fcos(elev_rad);
  2085.     /*
  2086.     gl_sincos(elevation, NULL, &cos_elev);
  2087.     */
  2088.     if (cos_elev != 0.0)
  2089.     {
  2090.  
  2091.     temp = ptw[2][0]/cos_elev;
  2092.     if (temp >= 1)
  2093.         azimuth = 900;
  2094.     else if (temp <= -1)
  2095.         azimuth = -900;
  2096.     else
  2097.     {
  2098.         temp = fasin(ptw[2][0]/cos_elev) * (1800.0/M_PI);
  2099.         /*
  2100.         temp = xasin(ptw[2][0]/cos_elev);
  2101.         */
  2102.         azimuth = (temp < 0)? temp-0.5: temp + 0.5;
  2103.     }
  2104.     if (ptw[2][2] < 0.0)        /* if heading into z    */
  2105.         azimuth = 1800 - azimuth;    /* then adjust        */
  2106.     if (azimuth < 0)
  2107.         azimuth += 3600;
  2108.  
  2109.     temp = xasin(ptw[0][1]/cos_elev);
  2110.     /*
  2111.     temp = fasin(ptw[0][1]/cos_elev) * (1800.0/M_PI);
  2112.     */
  2113.     twist = (temp < 0)? temp-0.5: temp + 0.5;
  2114.     if (ptw[1][1] < 0.0)        /* if upside down    */
  2115.         twist = 1800 - twist;
  2116.     if (twist < 0)
  2117.         twist += 3600;
  2118.     }
  2119.     last_px = pp->x;            /* save last position    */
  2120.     last_py = pp->y;
  2121.     last_pz = pp->z;
  2122.     pp->x = ptw[3][0];
  2123.     pp->y = ptw[3][1];
  2124.     pp->z = ptw[3][2];
  2125.     climbspeed = TPS * (pp->y - last_py);
  2126.  
  2127.     wm_x[wmspos] = pp->x;
  2128.     wm_y[wmspos] = pp->y;
  2129.     wm_z[wmspos] = pp->z;
  2130.     wm_twist[wmspos] = twist;
  2131.     wm_elevation[wmspos] = elevation;
  2132.     wm_azimuth[wmspos] = azimuth;
  2133.     wmpos = wmspos - wmfollow;
  2134.     if (wmpos < 0)
  2135.     wmpos += 10;
  2136.     wmspos = (wmspos+1) % 10;
  2137.  
  2138.     /*
  2139.      *    perform incremental rotations on velocities
  2140.      */
  2141.     identify_matrix(incremental);
  2142.     if (roll_speed) matrix_rotate(incremental, -roll_speed, 'z');
  2143.     if (elevation_speed) matrix_rotate(incremental, -elevation_speed, 'x');
  2144.     if (azimuth_speed) matrix_rotate(incremental, -azimuth_speed, 'y');
  2145.     matrix_translate(incremental, vx, vy, vz);
  2146.     vx = incremental[3][0];
  2147.     vy = incremental[3][1];
  2148.     vz = incremental[3][2];
  2149. }
  2150.  
  2151.  
  2152. /*
  2153.  *  test_position() tests for colisions, landing and flame out.
  2154.  */
  2155. test_position()
  2156. {
  2157.     Plane pp = planes[0];
  2158.  
  2159.     /*
  2160.      *  check altitude for too high, and landing/takeoff
  2161.      */
  2162.     if (pp->y > 50000.0)
  2163.     throttle = thrust = pp->thrust = 0;    /* flame out        */
  2164.     else if ((pp->y - plane_height) > 4.0)    /* not on ground    */
  2165.     {
  2166.     if (on_ground)            /* if was on ground    */
  2167.     {
  2168.         clear_report_card();        /* clear report card    */
  2169.         Cdp /= 3.0;            /* decrease drag    */
  2170.         min_throttle = 0;        /* no reverse engines    */
  2171.         on_ground = FALSE;
  2172.     }
  2173.     }
  2174.     else if ((pp->y - plane_height) < .5)    /* check for on the ground */
  2175.     {
  2176.     if (IN_BOX(pp,  -800.0,  100.0, -9500.0,  1000.0) ||
  2177.         IN_BOX(pp,   100.0, 1300.0, -2500.0, -1500.0) ||
  2178.         IN_BOX(pp, -2300.0, -800.0, -4900.0, -2000.0))
  2179.     {
  2180.         /*
  2181.          *  landing on a runway
  2182.          */
  2183.         if (!on_ground)
  2184.         {
  2185.         int rating, nm;
  2186.  
  2187.         Cdp *= 3.0;            /* increase drag    */
  2188.  
  2189.         rating = report_card(-climbspeed, twist, (int)(vx * TPS),
  2190.                      (int)(-vz * fps_knots), wheels, pp);
  2191.  
  2192.         if (rating == -1)        /* oops - you crashed    */
  2193.         {
  2194.             pp->status = MEXPLODE;    /* set to exploding    */
  2195.             pp->lost++;        /* increment count    */
  2196.         }
  2197.         else
  2198.         {
  2199.             fuel += rating << 7;
  2200.             if (fuel > (100 << 7))
  2201.             fuel = 100 << 7;
  2202.             max_throttle = 100;
  2203.         }
  2204.         min_throttle = -max_throttle; /* allow reverse engines*/
  2205.  
  2206.         rating = rating/10;    /* number of added missiles    */
  2207.  
  2208.         /*
  2209.          *  add sidewinders
  2210.          */
  2211.         nm = MAX_SW - sidewinders;        /* need this many */
  2212.         if (nm > 0)
  2213.         {
  2214.             if (nm > rating)
  2215.             nm = rating;        /* get this many */
  2216.             sidewinders += nm;
  2217.             rating -= nm;
  2218.         }
  2219.  
  2220.         /*
  2221.          *  add rockets
  2222.          */
  2223.         nm = MAX_RK - rockets;        /* need this many */
  2224.         if (nm > 0)
  2225.         {
  2226.             if (nm > rating)
  2227.             nm = rating;    /* get this many */
  2228.             rockets += nm;
  2229.         }
  2230.  
  2231.         test_mode = FALSE;
  2232.         fuel_rate = fuel_consump(Mthrust, W);
  2233.         rebuild_status();
  2234.         }
  2235.     }
  2236.     else
  2237.     {
  2238.         if (pp->status > MEXPLODE)
  2239.         {
  2240.         make_crash("You crashed into the swamps");
  2241.         broadcast("crashed into the swamps");
  2242.         }
  2243.         else if (!on_ground)
  2244.         {
  2245.         pp->status = MEXPLODE;    /* set to exploding    */
  2246. #ifdef AUDIO
  2247.         play_samps(diesample, dielength);
  2248. #endif
  2249.         }
  2250.     }
  2251.  
  2252.     ptw[3][1] = 0.0;
  2253.     pp->y = plane_height;
  2254.     on_ground = TRUE;
  2255.     if (pp->status > MEXPLODE)
  2256.     {
  2257.         if (elevation < 0) elevation = 0;/* kill negative elevation */
  2258.         if (twist != 0) twist = 0;    /* kill any twist    */
  2259.     }
  2260.     }
  2261. #ifdef AUDIO
  2262.     if (pp->thrust != oldthrust)
  2263.     pitch_thrust((float)(oldthrust = pp->thrust)/100.0);
  2264. #endif
  2265.  
  2266.     /*
  2267.      *  check for collision with hills
  2268.      */
  2269.     if (!in_cmode)
  2270.     if (collide_grid(pp->x, pp->y, pp->z, hillsgrid))
  2271.     {
  2272.         if (pp->status > MEXPLODE)
  2273.         {
  2274.         make_crash("You crashed into a hill");
  2275.         broadcast("crashed into a hill");
  2276.         }
  2277.         else if (!on_hill)
  2278.         {
  2279.         pp->status = MEXPLODE;    /* set to exploding    */
  2280. #ifdef AUDIO
  2281.         play_samps(diesample, dielength);
  2282. #endif
  2283.  
  2284.         }
  2285.         on_hill = TRUE;
  2286.     }
  2287. }
  2288.  
  2289.  
  2290. /*
  2291.  *  update_missiles() updates the position and status of missiles.
  2292.  *  It also launches a SAM if appropriate.
  2293.  */
  2294. update_missiles()
  2295. {
  2296.     Plane pp = planes[0], ptemp;
  2297.     float temp;
  2298.  
  2299.     /*
  2300.      *  SAM threats
  2301.      */
  2302.     if (threat_mode &&
  2303.     (tick_counter & 1) &&
  2304.     (pp->mtype != TYPE_SAM || !pp->mstatus) &&
  2305.     pp->y > 200.0)
  2306.     {
  2307.     register float dx, dy, dz;
  2308.     int launch_sam;
  2309.  
  2310.     /*
  2311.      *  test for proximity to SAM threats
  2312.      */
  2313.     dy = pp->y * pp->y;
  2314.     dx = 3000 - pp->x;
  2315.     dz = 34000 - pp->z;
  2316.     if (dx*dx + dz*dz + dy < 2700.0*2700.0)
  2317.     {
  2318.         pp->mx = 3000;
  2319.         pp->mz = 34000;
  2320.         launch_sam = TRUE;
  2321.     }
  2322.     else
  2323.     {
  2324.         dx = 6000 - pp->x;
  2325.         dz = 14000 - pp->z;
  2326.         if (dx*dx + dz*dz + dy < 17000.0*17000.0)
  2327.         {
  2328.         pp->mx = 6000;
  2329.         pp->mz = 14000;
  2330.         launch_sam = TRUE;
  2331.         }
  2332.         else
  2333.         {
  2334.         dx = -20000 - pp->x;
  2335.         dz = 15000 - pp->z;
  2336.         if (dx*dx + dz*dz + dy < 10700.0*10700.0)
  2337.         {
  2338.             pp->mx = -20000;
  2339.             pp->mz = 15000;
  2340.             launch_sam = TRUE;
  2341.         }
  2342.         else launch_sam = FALSE;
  2343.         }
  2344.     }
  2345.  
  2346.     /*
  2347.      *  if close enuf, take over a missile
  2348.      */
  2349.     if (launch_sam)
  2350.     {
  2351.         pp->my = 50;
  2352.         pp->mkill = NULL_PLANE_ID;
  2353.         pp->mtype = TYPE_SAM;
  2354.         pp->mstatus = MSTART;
  2355.  
  2356.         missile_target = PLANE_ID(pp);
  2357.         missile_vx = 0;
  2358.         missile_vy = 500.0/TPS;
  2359.         missile_vz = 0;
  2360.  
  2361.         sprintf(charbuf, "SAMissile->%s", pp->myname);
  2362.         set_text_meter(0, charbuf, -1);
  2363.  
  2364.         tick_counter = 2;
  2365.         rebuild_status();
  2366.     }
  2367.     }
  2368.  
  2369.     /*
  2370.      *  update MISSILES
  2371.      */
  2372.     if (pp->mstatus)            /* if missile launched    */
  2373.     {
  2374.     if (pp->mstatus > MEXPLODE)    /* if not exploding    */
  2375.     {
  2376.         pp->last_mx = pp->mx;        /* save last position    */
  2377.         pp->last_my = pp->my;
  2378.         pp->last_mz = pp->mz;
  2379.         pp->mx += missile_vx;        /* update position    */
  2380.         pp->my += missile_vy;
  2381.         pp->mz += missile_vz;
  2382.         if (pp->mtype == TYPE_CANNON)
  2383.         {
  2384.         pp->last_mx = .2 * pp->last_mx + .8 * pp->mx;
  2385.         pp->last_my = .2 * pp->last_my + .8 * pp->my;
  2386.         pp->last_mz = .2 * pp->last_mz + .8 * pp->mz;
  2387.         }
  2388.         if (pp->my < 10.0)        /* if too low, explode    */
  2389.         {
  2390.         pp->my = 20.0;
  2391.         if (pp->mtype == TYPE_CANNON)
  2392.             pp->mstatus = 1;    /* kill a cannon shot    */
  2393.         else
  2394.             pp->mstatus = MEXPLODE;
  2395.         }
  2396.         if (!in_cmode)
  2397.         if (collide_grid(pp->mx, pp->my - 10.0, pp->mz, hillsgrid))
  2398.         {
  2399.             if (pp->mtype == TYPE_CANNON)
  2400.             pp->mstatus = 1;    /* kill a cannon shot    */
  2401.             else
  2402.             pp->mstatus = MEXPLODE;
  2403.         }
  2404.         if (pp->mstatus == MFINISH)        /* coasting */
  2405.         {
  2406.         missile_vx *= .995;        /* air resistance hack */
  2407.         missile_vy *= .9975;
  2408.         missile_vz *= .995;
  2409.         missile_vy -= GRAVITY;        /* gravity */
  2410.         missile_target = NULL_PLANE_ID;
  2411.         if (pp->mtype == TYPE_CANNON)
  2412.             pp->mstatus = 1;        /* kill a cannon shot */
  2413.         else if (pp -> mtype == TYPE_SAM)
  2414.             pp -> mstatus = MEXPLODE;   /* or a SAM */
  2415.         else
  2416.             pp->mstatus++;        /* else continue to coast */
  2417.         }
  2418.         else    /* not finished - still has gas    */
  2419.         {
  2420.         float dx, dy, dz, acc, ticks, dvx, dvy, dvz;
  2421.  
  2422.         ticks = pp->mstatus - MFINISH;
  2423.         if (missile_target == NULL_PLANE_ID)
  2424.             ptemp = NULL;
  2425.         else
  2426.             ptemp = lookup_plane(missile_target);
  2427.  
  2428.         if (ptemp == NULL)
  2429.         {
  2430.             dx = missile_vx;
  2431.             dy = missile_vy;
  2432.             dz = missile_vz;
  2433.             acc = GRAVITY * .25 * ticks;
  2434.         }
  2435.         else    /* lock on the target    */
  2436.         {
  2437.             static float last_tpx, last_tpy, last_tpz;
  2438.             int txi, tyi, tzi;    /* time to intercept    */
  2439.  
  2440.             if (pp->mstatus == MSTART)
  2441.             {
  2442.             last_tpx = ptemp->x;
  2443.             last_tpy = ptemp->y;
  2444.             last_tpz = ptemp->z;
  2445.             }
  2446.             dx = ptemp->x - pp->mx;
  2447.             dy = ptemp->y - pp->my;
  2448.             dz = ptemp->z - pp->mz;
  2449.             dvx = (ptemp->x - last_tpx) - missile_vx;
  2450.             dvy = (ptemp->y - last_tpy) - missile_vy;
  2451.             dvz = (ptemp->z - last_tpz) - missile_vz;
  2452.             if (fabs(dvx) < .00001)
  2453.             txi = MLIFE;
  2454.             else
  2455.             {
  2456.             txi = dx/-dvx;
  2457.             if (txi < 0)
  2458.                 txi = -txi;
  2459.             }
  2460.             if (fabs(dvy) < .00001)
  2461.             tyi = MLIFE;
  2462.             else
  2463.             {
  2464.             tyi = dy/-dvy;
  2465.             if (tyi < 0)
  2466.                 tyi = -tyi;
  2467.             }
  2468.             if (fabs(dvz) < .00001)
  2469.             tzi = MLIFE;
  2470.             else
  2471.             {
  2472.             tzi = dz/-dvz;
  2473.             if (tzi < 0)
  2474.                 tzi = -tzi;
  2475.             }
  2476. #ifdef DEBUG
  2477. if (debug & (1<<4))
  2478. {
  2479.     printf("Status:%3d  Time x,y,z: %3d %3d %3d", pp->mstatus, txi, tyi, tzi);
  2480.     printf("    Dist: %d", itemp = sqrt(dx*dx + dy*dy + dz*dz));
  2481.     if (itemp < 250)
  2482.     printf(" <== killed *****\n");
  2483.     else
  2484.     printf("\n");
  2485. }
  2486. #endif
  2487.             /*
  2488.              *  find maximum intercept time
  2489.              */
  2490.             if (tyi > txi)
  2491.             txi = tyi;
  2492.             if (tzi > txi)
  2493.             txi = tzi;
  2494.             if (txi > MLIFE)
  2495.             txi = MLIFE;
  2496.  
  2497.             if (txi == 0)
  2498.             temp = 1.7/.2;
  2499.             else
  2500.             temp = 1.7/txi;            /* cut it by 1.7 */
  2501.             dx = temp * dx + dvx;        /* and aim for it */
  2502.             dy = temp * dy + dvy;
  2503.             dz = temp * dz + dvz;
  2504.             if (pp->mtype == TYPE_SIDEWINDER)
  2505.             acc = 16.0 * GRAVITY;        /* with 16 G's  */
  2506.             else
  2507.             acc = 20.0 * GRAVITY;        /* with 20 G's  */
  2508.  
  2509.             /*
  2510.              *  save target's last pos
  2511.              */
  2512.             last_tpx = ptemp->x;
  2513.             last_tpy = ptemp->y;
  2514.             last_tpz = ptemp->z;
  2515.         }
  2516.         if (pp->mtype != TYPE_CANNON)
  2517.         {
  2518.             temp = acc / (fabs(dx) + fabs(dy) + fabs(dz));
  2519.             missile_vx += dx * temp;
  2520.             missile_vy += dy * temp;
  2521.             missile_vz += dz * temp;
  2522.         }
  2523.         }
  2524.  
  2525.     }    /* end of if (pp->mstatus > MEXPLODE)    */
  2526.     else
  2527.         missile_target = NULL_PLANE_ID;
  2528.  
  2529. #ifdef AUDIO
  2530.     if (pp->mstatus == MEXPLODE)
  2531.         if (view_switch == PLANE_VIEW && missile_view)
  2532.         play_explosion(1.0);    /* use max volume -> small dist */
  2533.         else
  2534.         play_explosion((pp->x - pp->mx)*(pp->x - pp->mx) +
  2535.                    (pp->y - pp->my)*(pp->y - pp->my) +
  2536.                    (pp->z - pp->mz)*(pp->z - pp->mz));
  2537. #endif
  2538.  
  2539.     pp->mstatus--;        /* decrement status    */
  2540.  
  2541.     if (pp->mstatus == 0)
  2542.         set_text_meter(0, "", -1);
  2543.     }
  2544. }
  2545.  
  2546.  
  2547. /*
  2548.  *  do_flight() is the actual flight equasion code
  2549.  */
  2550. do_flight()
  2551. {
  2552.     float temp;
  2553.     int itemp;
  2554.     short vz_positive;            /* true if vz >= 0 */
  2555.     Plane pp = planes[0];
  2556.  
  2557.     static float ax, ay, az;        /* plane acceleration        */
  2558.     static float ydrag, zdrag;        /* drag force in y and z    */
  2559.     static float ae;            /* angle of attack for wing    */
  2560.     static float ro2, sos;        /* air density / 2.0, speed of sound */
  2561.     static float mcc, mratio;        /* mach crest critical #, mach/mcc */
  2562.     static float uCl, Cl, Cd, Cdc;    /* coefficients of lift and drag */
  2563.     static float kl, qs;        /* ground effect, ro/2*Vz*s    */
  2564.  
  2565.     /* XXX
  2566.     if (pp->status > MEXPLODE)
  2567.     if (1)
  2568.     */
  2569.     if ((pp->status || !on_ground) && !on_hill)
  2570.     {
  2571.     /* ground effect factor    */
  2572.     if ((pp->y - plane_height) > gefy)
  2573.         kl = 1.0;
  2574.     else
  2575.     {
  2576.         kl = (pp->y - plane_height) / b;
  2577.         if (kl > .225)
  2578.         kl = .484 * kl + .661;
  2579.         else
  2580.         kl = 2.533 * kl + .20;
  2581.     }
  2582.  
  2583.     /* compute new accelerations, lift: only if vz is negative    */
  2584.     vz_positive = (vz >= 0.0);
  2585.     if (!vz_positive)
  2586.     {
  2587.         ae = vy/vz + tilt_factor;
  2588.         Cl = uCl = ae/(.17 + kl*ipi_AR);
  2589.         if (Cl > max_cl)        /* check for positive stall    */
  2590.         {
  2591.         Cl = 3.0 * max_cl - 2.0 * Cl;
  2592.         wing_stall = 1;
  2593.         if (Cl < 0.0)
  2594.         {
  2595.             wing_stall += 1 - (int)(Cl/max_cl);
  2596.             Cl = 0.0;
  2597.         }
  2598.         if (uCl > 5.0)
  2599.             uCl = 5.0;
  2600.         }
  2601.         else if (Cl < min_cl)    /* check for negative stall    */
  2602.         {
  2603.         Cl = 3.0 * min_cl - 2.0 * Cl;
  2604.         wing_stall = 1;
  2605.         if (Cl > 0.0)
  2606.         {
  2607.             wing_stall += 1 - (int)(Cl/min_cl);
  2608.             Cl = 0.0;
  2609.         }
  2610.         if (uCl < -5.0)
  2611.             uCl = -5.0;
  2612.         }
  2613.         else
  2614.         wing_stall = FALSE;
  2615.     }
  2616.     else
  2617.     {
  2618.         Cl = uCl = 0.0;
  2619.         wing_stall = on_ground ? 0 : vz;
  2620.         ae = 0;
  2621.     }
  2622.     if (wing_stall > 64)
  2623.         wing_stall = 64;
  2624.  
  2625.     if ((tick_counter & 1) == 0)    /* only do on even ticks    */
  2626.     {
  2627.         if (pp->y <= 36000.0)    /* compute speed of sound    */
  2628.         sos = -1116.0/TPS + (1116.0-968.0)/TPS/36000.0 * pp->y;
  2629.         else
  2630.         sos = -968.0/TPS;
  2631.         itemp = ((int)pp->y) >> 10;
  2632.         if (itemp > 74)
  2633.         itemp = 74;
  2634.         ro2 = .5 * ro[itemp];
  2635.         if (Cl < .2)
  2636.         mcc = .7166666 + .1666667 * Cl;
  2637.         else
  2638.         mcc = .7833333 - .1666667 * Cl;
  2639.         mach = vz/sos;        /* and current mach number    */
  2640.         mratio = mach/mcc;
  2641.         if (mratio < 1.034)
  2642.         Cdc = 0.0;
  2643.         else
  2644.         {
  2645.         Cdc = .082 * mratio - 0.084788;
  2646.         if (Cdc > .03)
  2647.             Cdc = .03;
  2648.         }
  2649.         if (spoilers > 0)
  2650.         Cdc += Spdf;
  2651.     }
  2652.  
  2653.     qs = ro2 * vz * s;        /* assume V approx = vz    */
  2654.  
  2655.     lift = Cl * qs;
  2656.     g_limit = FALSE;
  2657.     if (spoilers > 0)
  2658.         lift *= Splf;
  2659.     relift:
  2660.     ay = vz * lift;
  2661.     az = -vy * lift;
  2662.     lift = ay * inverse_mass;    /* save for wing loading meter    */
  2663.     if (lift > Lmax_g)
  2664.     {
  2665.         lift = .99 * Lmax_g/inverse_mass/vz;
  2666.         g_limit = TRUE;
  2667.         goto relift;
  2668.     }
  2669.     else if (lift < Lmin_g)
  2670.     {
  2671.         lift = .99 * Lmin_g/inverse_mass/vz;
  2672.         g_limit = TRUE;
  2673.         goto relift;
  2674.     }
  2675.  
  2676.     /* engine thrust        */
  2677.     if (thrust < throttle)
  2678.     {
  2679.         thrust += (50.0/tps);    /* 2 seconds to rev to full 100% */
  2680.         if (thrust > throttle)
  2681.         thrust = throttle;
  2682.     }
  2683.     else if (thrust > throttle)
  2684.     {
  2685.         thrust -= (50.0/tps);    /* 2 seconds to rev to full 100% */
  2686.         if (thrust < throttle)
  2687.         thrust = throttle;
  2688.     }
  2689.     pp->thrust = thrust;
  2690.     az -= .01/TPS/TPS*thrust * Mthrust;
  2691.  
  2692.     /* drag - needs to be broken into y/z components        */
  2693.     Cd = Cdp + kl*uCl*uCl*ie_pi_AR + Cdc;
  2694.     zdrag = Cd * qs;
  2695.     ydrag = vy * zdrag;
  2696.     zdrag = vz * zdrag;
  2697.     if (vz_positive)        /* if vz is positive    */
  2698.     {
  2699.         ay -= ydrag;
  2700.         az -= zdrag;
  2701.     }
  2702.     else
  2703.     {
  2704.         ay += ydrag;
  2705.         az += zdrag;
  2706.     }
  2707.  
  2708.     /* now convert forces to accelerations (A=F/M)    */
  2709.     ax = 0.0;
  2710.     ay *= inverse_mass;
  2711.     az *= inverse_mass;
  2712.  
  2713.     /* add in gravity which is an acceleration    */
  2714.     ax -= ptw[0][1] * GRAVITY;
  2715.     ay -= ptw[1][1] * GRAVITY;
  2716.     az -= ptw[2][1] * GRAVITY;
  2717.  
  2718.     vx += ax;    vz += az;
  2719.     if (on_ground && pp->status > MEXPLODE)
  2720.     {
  2721.         float cos;
  2722.  
  2723.         vx = 0.0;
  2724.         gl_sincos(elevation, &temp, &cos);
  2725.         temp = vz * temp/cos;
  2726.         if (vy+ay < temp)
  2727.         ay = temp - vy;
  2728.     }
  2729.     vy += ay;
  2730.  
  2731.     /*
  2732.      *  use fuel
  2733.      */
  2734.     if (tick_counter == 2 && fuel > 0)
  2735.     {
  2736.         fuel -= (int)(_ABS(thrust) * fuel_rate);
  2737.         inverse_mass = compute_mass();
  2738.     }
  2739.     }
  2740.     else /* plane has exploded */
  2741.     {
  2742.     wing_stall = FALSE;    /* so the bell will stop ringing */
  2743.     }
  2744.  
  2745.  
  2746. #ifdef DEBUG
  2747. if (debug & (1<<1))
  2748. {
  2749.     temp = inverse_mass * TPS *TPS;
  2750.     printf("----------------------%d----------------------\n", tick_counter);
  2751.     printf("Position (xyz): %12.2f%12.2f%12.2f    %s\n",
  2752.         pp->x, pp->y, pp->z, on_ground?"*** ON THE GROUND":"");
  2753.     printf("Elevation, azimuth, roll: %6d%6d%6d\n",
  2754.             elevation, azimuth, twist);
  2755.     printf("Elev, azim, roll speeds:  %6d%6d%6d\n",
  2756.             elevation_speed, azimuth_speed, roll_speed);
  2757.     printf("Rotated velocities per tick: %9.2f%9.2f%9.2f\n",
  2758.     incremental[3][0]*TPS, incremental[3][1]*TPS, incremental[3][2]*TPS);
  2759.     printf("Speed-of-sound:%8.1f  Mach:%5.2f  Mcc:%5.2f  Mach/Mcc:%5.2f\n",
  2760.         -sos*TPS, mach, mcc, mratio);
  2761.     printf("Cd:%8.4f=%7.4f +%7.4f +%7.4f  (p+i+c)\n",
  2762.         Cd, Cdp, kl*uCl*uCl*ie_pi_AR, Cdc);
  2763.     printf("Cl:%5.2f  kl:%5.2f  ro2:%7.4f  qs:%6.2f\n",
  2764.         Cl, kl, ro2, TPS*TPS*vz*qs);
  2765.     printf("Thrust:   %21.2f\n", -.01*thrust * Mthrust * inverse_mass);
  2766.     if (spoilers > 0)
  2767.     qs *= Splf;
  2768.     printf("Lift:     %14.2f%7.2f        angle:%6.2f\n",
  2769.         vz*Cl*qs*temp, -vy*Cl*qs*temp, 57.3 * (ae-tilt_factor));
  2770.     printf("Drag:     %14.2f%7.2f\n", ydrag*temp, zdrag*temp);
  2771.     printf("Gravity:  %7.2f%7.2f%7.2f\n",
  2772.         ptw[0][1]*-G_ACC, ptw[1][1]*-G_ACC, ptw[2][1]*-G_ACC);
  2773.     printf("-------------------------------   Mass: %g\n", G_ACC/inverse_mass);
  2774.     printf("Totals:   %7.2f%7.2f%7.2f\n", ax*TPS*TPS, ay*TPS*TPS, az*TPS*TPS);
  2775.     printf("New velocities per tick: %9.2f%9.2f%9.2f\n",
  2776.                 vx*TPS, vy*TPS, vz*TPS);
  2777. }
  2778. if (debug & (1<<5)) printf("Wing_stall = %d\n", wing_stall);
  2779. if (debug & (1<<3))
  2780. {
  2781.     if (pp->mstatus)
  2782.     {
  2783.     printf("----------------------------------------\n");
  2784.     printf("Missile status: %d\n", pp->mstatus);
  2785.     printf("Missile velocities (xyz): %12.2f%12.2f%12.2f\n",
  2786.             missile_vx*TPS, missile_vy*TPS, missile_vz*TPS);
  2787.     printf("Missile position (xyz):   %12.2f%12.2f%12.2f\n",
  2788.             pp->mx, pp->my, pp->mz);
  2789.     }
  2790. }
  2791. #endif
  2792. }
  2793.  
  2794.  
  2795. draw_scene()
  2796. {
  2797.     float fcp;        /* front clipping plane */
  2798.     Plane pp = planes[0];
  2799.     float mk_x,mk_y,mk_z,mk_len;  /* mk = missile kludge */
  2800.     Matrix tmpmat;
  2801.  
  2802.     /*
  2803.      *  set up windshield, and load perspective
  2804.      */
  2805.     if (shadow)
  2806.     {
  2807.     azimuth = pp->azimuth;
  2808.     elevation = pp->elevation;
  2809.     twist = pp->twist;
  2810.     }
  2811.     else
  2812.     {
  2813.     pp->azimuth = azimuth;
  2814.     pp->elevation = elevation;
  2815.     pp->twist = twist;
  2816.     }
  2817.  
  2818.     if (hud || shadow)
  2819.     viewport(0, xmaxwindow, 0, ymaxwindow);
  2820.     else
  2821.     viewport(1, xmaxwindow-1, ymiddle, ymaxwindow-1);
  2822.  
  2823.     if (view_switch == TOWER_VIEW)
  2824.     {
  2825.     if ((fcp = range(eye_x, eye_y, eye_z,
  2826.              pp->x, pp->y, pp->z) / 2.0) > 200.0)
  2827.         fcp = 200.0;
  2828.     else
  2829.         fcp = (fcp > 4.0)? fcp : 4.0;
  2830.     perspective(fov, ar, fcp, 1.0e6);
  2831.     }
  2832.     else
  2833.     {
  2834.     fcp = (pp->y < 20.0 || (wingman_view && wmfollow <= 1))? 4.0 : 10.0;
  2835.     perspective(fov, ar, fcp, 1.0e6);
  2836.     }
  2837.  
  2838.     loadmatrix(identmat);
  2839.     pushmatrix();
  2840.  
  2841.     if (fogit)
  2842.     fog(TRUE);
  2843.  
  2844.     if (view_switch == TOWER_VIEW)
  2845.     {
  2846.     identify_matrix(tmpmat);
  2847.     if (missile_view && pp->mstatus)
  2848.         my_lookat(eye_x, eye_y, eye_z, pp->mx, pp->my, pp->mz, tmpmat);
  2849.     else
  2850.         my_lookat(eye_x, eye_y, eye_z, pp->x, pp->y, pp->z, tmpmat);
  2851.     if (!in_cmode)
  2852.         lmbind(LIGHT0, SUN);
  2853.     draw_infinite_world();
  2854.  
  2855.     current_eye[X] = eye_x;
  2856.     current_eye[Y] = eye_y;
  2857.     current_eye[Z] = eye_z;
  2858.     calc_clip_planes(tmpmat, current_eye);
  2859.     }
  2860.     else if (view_switch == PLANE_VIEW)
  2861.     {
  2862.     if (missile_view && pp->mstatus)
  2863.     {
  2864.         Plane_hist ph = plane_hists[0];
  2865.  
  2866.         identify_matrix(tmpmat);
  2867.         translate(0.0, -missile_eye[Y], 0.0);
  2868.  
  2869.         vec_len(&pp->mx, &pp->last_mx, 30.0, current_eye);
  2870.  
  2871.         my_lookat(current_eye[X], current_eye[Y], current_eye[Z],
  2872.               pp->mx, pp->my, pp->mz, tmpmat);
  2873.  
  2874.         if (!in_cmode)
  2875.         lmbind(LIGHT0, SUN);
  2876.         draw_infinite_world();
  2877.  
  2878.         current_eye[Y] += missile_eye[Y];
  2879.         calc_clip_planes(tmpmat, current_eye);
  2880.     }
  2881.     else if (wingman_view)
  2882.     {
  2883.         if (view_angle != 0)
  2884.         rotate(view_angle, 'y');
  2885.  
  2886.         /* pilot's eye position */
  2887.         translate(0.0, -pilot_eye[Y], -pilot_eye[Z]);
  2888.  
  2889.         rotate(-wm_twist[wmpos], 'z');
  2890.         rotate(-wm_elevation[wmpos], 'x');
  2891.         rotate(-wm_azimuth[wmpos], 'y');
  2892.         if (!in_cmode)
  2893.         lmbind(LIGHT0, SUN);
  2894.         translate(0.0, -wm_y[wmpos], 0.0);
  2895.         draw_infinite_world();
  2896.         translate(-wm_x[wmpos], 0.0, -wm_z[wmpos]);
  2897.  
  2898.         identify_matrix(tmpmat);
  2899.         matrix_rotate(tmpmat, wm_azimuth[wmpos], 'y');
  2900.         matrix_rotate(tmpmat, wm_elevation[wmpos], 'x');
  2901.         matrix_rotate(tmpmat, wm_twist[wmpos], 'z');
  2902.         mult_vec(tmpmat, pilot_eye, current_eye);
  2903.         if (view_angle != 0)
  2904.         matrix_rotate(tmpmat, -view_angle, 'y');
  2905.         current_eye[X] += wm_x[wmpos];
  2906.         current_eye[Y] += wm_y[wmpos];
  2907.         current_eye[Z] += wm_z[wmpos];
  2908.         calc_clip_planes(tmpmat, current_eye);
  2909.     }
  2910.     else    /* just draw the view from the plane */
  2911.     {
  2912.         if (view_angle != 0)
  2913.         rotate(view_angle, 'y');
  2914.  
  2915.         /* pilot's eye position */
  2916.         translate(0.0, -pilot_eye[Y], -pilot_eye[Z]);
  2917.  
  2918.         rotate(-twist, 'z');
  2919.         rotate(-elevation, 'x');
  2920.         rotate(-azimuth, 'y');
  2921.         if (!in_cmode)
  2922.         lmbind(LIGHT0, SUN);
  2923.         translate(0.0, -pp->y, 0.0);
  2924.         draw_infinite_world();
  2925.         translate(-pp->x, 0.0, -pp->z);
  2926.  
  2927.         identify_matrix(tmpmat);
  2928.         matrix_rotate(tmpmat, azimuth, 'y');
  2929.         matrix_rotate(tmpmat, elevation, 'x');
  2930.         matrix_rotate(tmpmat, twist, 'z');
  2931.         mult_vec(tmpmat, pilot_eye, current_eye);
  2932.         if (view_angle != 0)
  2933.         matrix_rotate(tmpmat, -view_angle, 'y');
  2934.         current_eye[X] += pp->x;
  2935.         current_eye[Y] += pp->y;
  2936.         current_eye[Z] += pp->z;
  2937.         calc_clip_planes(tmpmat, current_eye);
  2938.     }
  2939.     }
  2940.  
  2941.     if (in_cmode)
  2942.     draw_world_ci();
  2943.     else
  2944.     draw_world();
  2945.  
  2946.     popmatrix();    /* Back to identity */
  2947.  
  2948.     if (hud)
  2949.     {
  2950.     ortho2(-0.5, xmaxwindow+0.5, -0.5, ymaxwindow+0.5);
  2951.     cmov2s(50, ymaxwindow-20);    /* position character origin    */
  2952.     }
  2953.     else if (shadow)
  2954.     {
  2955.     ortho2(-200.0,200.0,-200.0,200.0);
  2956.     draw_cross_hairs();
  2957.     cmov2s(-195,192);        /* position character origin    */
  2958.     }
  2959.     else
  2960.     {
  2961.     ortho2(-200.0,200.0,-100.0,100.0);
  2962.     draw_cross_hairs();
  2963.     cmov2s(-195,92);        /* position character origin    */
  2964.     }
  2965.  
  2966.     if (view_switch == PLANE_VIEW)
  2967.     {
  2968.     COLOR(C_ORANGE);
  2969.     if (view_angle == 0)
  2970.     {
  2971.         charstr("Front view");
  2972.         if (!hud)
  2973.         {
  2974.         setlinestyle(1);
  2975.         rects(-40, -40, 40, 40);
  2976.         setlinestyle(0);
  2977.         }
  2978.     }
  2979.     else if (view_angle == -900) charstr("Left view");
  2980.     else if (view_angle == 900) charstr("Right view");
  2981.     else if (view_angle == 1800) charstr("Back view");
  2982.     else
  2983.     {
  2984.         sprintf(charbuf, "%d degree view", view_angle / 10);
  2985.         charstr(charbuf);
  2986.     }
  2987.     if (shadow)
  2988.     {
  2989.         charstr(" of ");
  2990.         charstr(pp->myname);
  2991.     }
  2992.     }
  2993.  
  2994.     if (show_help)
  2995.     if (shadow)
  2996.         overlay_shadow_help();
  2997.     else
  2998.         overlay_help();
  2999. }
  3000.  
  3001.  
  3002. draw_world()
  3003. {
  3004.     Plane pp = planes[0];
  3005.  
  3006.     /*
  3007.      *  draw local objects
  3008.      */
  3009.     lighting(TRUE);
  3010.     zbuffer(TRUE);
  3011.     drawobj(mtnsobj, 0x1);
  3012.     zbuffer(FALSE);
  3013.     draw_grid();
  3014.     drawobj(runwayobj, 0x1);
  3015.     lighting(FALSE);
  3016.     if (lightson)
  3017.     drawobj(lightsobj, 0x1);
  3018.     draw_vasi(pp);            /* show VASI lights    */
  3019.  
  3020.     zbuffer(TRUE);
  3021.  
  3022.     if (threat_mode)
  3023.     draw_threats();
  3024.  
  3025.     lighting(TRUE);
  3026.  
  3027.     if (texit)
  3028.     texturing(TRUE);
  3029.     drawobj(hillsobj, 0x1);
  3030.     if (texit)
  3031.     texturing(FALSE);
  3032.  
  3033.     if (view_switch == TOWER_VIEW)
  3034.     {
  3035.     draw_buildings(eye_x, eye_y, eye_z);
  3036.     draw_planes(eye_x, eye_y, eye_z, 0, number_planes);
  3037.     }
  3038.     else if (missile_view && pp->mstatus)
  3039.     {
  3040.     draw_buildings(pp->last_mx, pp->last_my, pp->last_mz);
  3041.     draw_planes(pp->last_mx, pp->last_my, pp->last_mz, 0, number_planes);
  3042.     }
  3043.     else if (wingman_view)
  3044.     {
  3045.     draw_buildings(wm_x[wmpos], wm_y[wmpos], wm_z[wmpos]);
  3046.     draw_planes(wm_x[wmpos], wm_y[wmpos], wm_z[wmpos], 0, number_planes);
  3047.     }
  3048.     else
  3049.     {
  3050.     draw_buildings(pp->x, pp->y, pp->z);
  3051.     draw_planes(pp->x, pp->y, pp->z, 1, number_planes);
  3052.     }
  3053.  
  3054.     draw_missiles();
  3055.  
  3056.     lighting(FALSE);
  3057.  
  3058.     zbuffer(FALSE);
  3059.  
  3060.     if (fogit)
  3061.         fog(FALSE);
  3062. }
  3063.  
  3064.  
  3065. draw_world_ci()
  3066. {
  3067.     Plane pp = planes[0];
  3068.  
  3069.     /*
  3070.      *  draw local objects
  3071.      */
  3072.     drawobj(mtnsobj, 0x1);
  3073.  
  3074.     draw_grid();
  3075.  
  3076.     drawobj(runwayobj, 0x1);
  3077.  
  3078.     if (lightson)
  3079.     drawobj(lightsobj, 0x1);
  3080.  
  3081.     draw_vasi(pp);            /* show VASI lights    */
  3082.  
  3083.  
  3084.     if (view_switch == TOWER_VIEW)
  3085.     {
  3086.     draw_everything(eye_x, eye_y, eye_z, number_planes, 1);
  3087.     }
  3088.     else if (missile_view && pp->mstatus)
  3089.     {
  3090.     draw_everything(pp->last_mx, pp->last_my, pp->last_mz,
  3091.             number_planes, 1);
  3092.     }
  3093.     else if (wingman_view)
  3094.     {
  3095.     draw_everything(wm_x[wmpos], wm_y[wmpos], wm_z[wmpos],
  3096.             number_planes, 1);
  3097.     }
  3098.     else
  3099.     {
  3100.     draw_everything(pp->x, pp->y, pp->z, number_planes, 0);
  3101.     }
  3102. }
  3103.  
  3104.  
  3105. /*
  3106.  *  clean up and exit routine for flight
  3107.  */
  3108. end_of_program()
  3109. {
  3110. #ifdef AUDIO
  3111.     close_audio();
  3112. #endif
  3113.     ExitComm();
  3114.     greset();
  3115.     COLOR(C_BLACK);
  3116.     clear();
  3117.     restore_map();
  3118.     drawmode(over_drawmode);
  3119.     color(0);
  3120.     clear();
  3121.     if (bits_under)
  3122.     {
  3123.     drawmode(UNDERDRAW);
  3124.     color(0);
  3125.     clear();
  3126.     }
  3127.     exit(0);
  3128. }
  3129.  
  3130.  
  3131. draw_meters()
  3132. {
  3133.     if (hud)
  3134.     draw_hud(planes[0], tick_counter, vx, vy, vz, climbspeed, mach,
  3135.          lift/GRAVITY, wheels, flaps, spoilers, autopilot_on,
  3136.          fuel >> 7, thrust, throttle);
  3137.     else if (new_inst)
  3138.     update_instruments(0);
  3139.     else
  3140.     old_meters();
  3141. }
  3142.  
  3143.  
  3144. /*
  3145.  *  select a plane and set it's design parameters
  3146.  */
  3147. select_plane()
  3148. {
  3149.     Plane pp = planes[0];
  3150.  
  3151.     pp->type = -1;
  3152.  
  3153.     while (pp->type == -1)
  3154.     switch (pick_plane())
  3155.     {
  3156.         case 1:
  3157.         plane_type = C150_NAME;
  3158.         pp->type = C150;
  3159.         s = 157.0;
  3160.         W = 1000.0;
  3161.         fuel_weight = 400.0;
  3162.         set_fuelgauge(400.0, 100.0, 10, 100);
  3163.         Mthrust = 300.0;
  3164.         b = 28.0;
  3165.         ef = .80;
  3166.         Lmax = 5.0;    Lmin = -3.0;
  3167.         Fmax = 20;    Smax = 0;
  3168.         set_flapspoiler(20, 20, 4, 0, 0, 0);
  3169.         MAX_RK = 0;    MAX_SW = 0;
  3170.         MIN_LIFT_SPEED = 70;
  3171.         ELEVF = 75.0;
  3172.         ROLLF = 130.0;
  3173.         landing_gear_stuck = 1;    /* stuck down    */
  3174.         pilot_eye[Y] = 5.0;
  3175.         pilot_eye[Z] = 0.0;
  3176.         plane_height = 1.5;
  3177. #ifdef AUDIO
  3178.         thrust_type(0);
  3179. #endif
  3180.         break;
  3181.         case 2:
  3182.         plane_type = B747_NAME;
  3183.         pp->type = B747;
  3184.         s = 5500.0;        /* wing area in sq. feet    */
  3185.         W = 500000.0;        /* weight of plane in lbs.    */
  3186.         fuel_weight = 100000.0;
  3187.         set_fuelgauge(100000.0, 10000.0, 2, 10000);
  3188.         Mthrust = 200000.0;    /* maximum thrust        */
  3189.         b = 220.0;        /* wing span in feet        */
  3190.         ef = .83;        /* efficiency factor        */
  3191.         Lmax = 4.0;        /* maximum lift before wing breaks */
  3192.         Lmin = -2.0;        /* minimum lift before wing breaks */
  3193.         Fmax = 50;        /* maximum flap deflection    */
  3194.         Smax = 80;        /* maximum spoiler deflection    */
  3195.         set_flapspoiler(50, 50, 10, 80, 80, 8);
  3196.         MAX_RK = 0;
  3197.         MAX_SW = 0;
  3198.         MIN_LIFT_SPEED = 200;
  3199.         ELEVF = 25.0;        /* elevator rate in degrees/sec    */
  3200.         ROLLF = 50.0;        /* roll rate (both at 300 mph)    */
  3201.         pilot_eye[Y] = 30.0;
  3202.         pilot_eye[Z] = -92.0;
  3203.         plane_height = 0.0;
  3204. #ifdef AUDIO
  3205.         thrust_type(0);
  3206. #endif
  3207.         break;
  3208.         case 3:
  3209.         plane_type = F15_NAME;
  3210.         pp->type = F15;
  3211.         s = 608.0;
  3212.         W = 28000.0;
  3213.         fuel_weight = 14000.0;
  3214.         set_fuelgauge(14000.0, 2000.0, 5, 1000);
  3215.         Mthrust = 46000.0;
  3216.         b = 43.0;
  3217.         ef = .87;
  3218.         Lmax = 8.0;    Lmin = -5.0;
  3219.         Fmax = 30;    Smax = 60;
  3220.         set_flapspoiler(30, 30, 6, 60, 60, 6);
  3221.         MAX_RK = 4;    MAX_SW = 4;
  3222.         swpos[3][X] =   9.0; swpos[3][Y] =  0.0; swpos[3][Z] = 3.0;
  3223.         swpos[2][X] =  -9.0; swpos[2][Y] =  0.0; swpos[2][Z] = 3.0;
  3224.         swpos[1][X] =   9.0; swpos[1][Y] =  0.0; swpos[1][Z] = 3.0;
  3225.         swpos[0][X] =  -9.0; swpos[0][Y] =  0.0; swpos[0][Z] = 3.0;
  3226.         rkpos[3][X] =  -2.0; rkpos[3][Y] = -1.0; rkpos[3][Z] = 3.0;
  3227.         rkpos[2][X] =   2.0; rkpos[2][Y] = -1.0; rkpos[2][Z] = 3.0;
  3228.         rkpos[1][X] =  -2.0; rkpos[1][Y] = -1.0; rkpos[1][Z] = 3.0;
  3229.         rkpos[0][X] =   2.0; rkpos[0][Y] = -1.0; rkpos[0][Z] = 3.0;
  3230.         MIN_LIFT_SPEED = 100;
  3231.         ELEVF = 32.0;
  3232.         ROLLF = 140.0;
  3233.         pilot_eye[Y] = 4.8;
  3234.         pilot_eye[Z] = -26.0;
  3235.         plane_height = 4.89;
  3236.         /*
  3237.         pilot_eye[Y] = 10.0;
  3238.         pilot_eye[Z] = -25.0;
  3239.         plane_height = 4.0;
  3240.         */
  3241. #ifdef AUDIO
  3242.         thrust_type(1);
  3243. #endif
  3244.         break;
  3245.         case 4:
  3246.         plane_type = F16_NAME;
  3247.         pp->type = F16;
  3248.         s = 390.0;
  3249.         W = 18000.0;
  3250.         fuel_weight = 8000.0;
  3251.         set_fuelgauge(8000.0, 1000.0, 5, 1000);
  3252.         Mthrust = 23000.0;
  3253.         b = 32.0;
  3254.         ef = .93;
  3255.         Lmax = 10.0; Lmin = -7.0;
  3256.         Fmax = 40;    Smax = 40;
  3257.         set_flapspoiler(40, 40, 4, 40, 40, 4);
  3258.         MAX_RK = 2;    MAX_SW = 2;
  3259.         swpos[1][X] =  14.8; swpos[1][Y] = -2.0; swpos[1][Z] = 4.6334;
  3260.         swpos[0][X] = -14.8; swpos[0][Y] = -2.0; swpos[0][Z] = 4.6334;
  3261.         rkpos[1][X] =  -6.0; rkpos[1][Y] = -2.0; rkpos[1][Z] = 4.6334;
  3262.         rkpos[0][X] =   6.0; rkpos[0][Y] = -2.0; rkpos[0][Z] = 4.6334;
  3263.         MIN_LIFT_SPEED = 120;
  3264.         ELEVF = 34.0;
  3265.         ROLLF = 180.0;
  3266.         pilot_eye[Y] = 3.5;
  3267.         pilot_eye[Z] = -13.0;
  3268.         plane_height = 4.0;
  3269. #ifdef AUDIO
  3270.         thrust_type(1);
  3271. #endif
  3272.         break;
  3273.         case 5:
  3274.         plane_type = F18_NAME;
  3275.         pp->type = F18;
  3276.         s = 510.0;
  3277.         W = 24000.0;
  3278.         fuel_weight = 12000.0;
  3279.         set_fuelgauge(12000.0, 2000.0, 5, 1000);
  3280.         Mthrust = 32000.0;
  3281.         b = 38.0;
  3282.         ef = .90;
  3283.         Lmax = 9.0;    Lmin = -6.0;
  3284.         Fmax = 50;    Smax = 60;
  3285.         set_flapspoiler(50, 50, 5, 60, 60, 6);
  3286.         MAX_RK = 3;    MAX_SW = 3;
  3287.         swpos[2][X] = -18.2; swpos[2][Y] =  0.0; swpos[2][Z] = 7.2;
  3288.         swpos[1][X] =  18.2; swpos[1][Y] =  0.0; swpos[1][Z] = 7.2;
  3289.         swpos[0][X] =   0.0; swpos[0][Y] = -2.0; swpos[0][Z] = 7.2;
  3290.         rkpos[2][X] =   8.2; rkpos[2][Y] =  0.0; rkpos[2][Z] = 7.2;
  3291.         rkpos[1][X] =  -8.2; rkpos[1][Y] =  0.0; rkpos[1][Z] = 7.2;
  3292.         rkpos[0][X] =   0.0; rkpos[0][Y] = -2.0; rkpos[0][Z] = 7.2;
  3293.         MIN_LIFT_SPEED = 110;
  3294.         ELEVF = 30.0;
  3295.         ROLLF = 170.0;
  3296.         pilot_eye[Y] = 4.3;
  3297.         pilot_eye[Z] = -13.5;
  3298.         plane_height = 4.565;
  3299. #ifdef AUDIO
  3300.         thrust_type(1);
  3301. #endif
  3302.         break;
  3303.         case 6:
  3304.         plane_type = P38_NAME;
  3305.         pp->type = P38;
  3306.         s = 327.5;
  3307.         W = 13500.0;
  3308.         fuel_weight = 1600.0;
  3309.         set_fuelgauge(1600.0, 200.0, 5, 100);
  3310.         Mthrust = 4000.0;
  3311.         b = 52.0;
  3312.         ef = .90;
  3313.         Lmax = 6.0;    Lmin = -3.5;
  3314.         Fmax = 50;    Smax = 60;
  3315.         set_flapspoiler(50, 50, 5, 60, 60, 6);
  3316.         MAX_RK = 2;    MAX_SW = 0;
  3317.         rkpos[1][X] = -16.0; rkpos[1][Y] =  0.0; rkpos[1][Z] = 0.0;
  3318.         rkpos[0][X] =  16.0; rkpos[0][Y] =  0.0; rkpos[0][Z] = 0.0;
  3319.         MIN_LIFT_SPEED = 75;
  3320.         ELEVF = 30.0;
  3321.         ROLLF = 100.0;
  3322.         pilot_eye[Y] = 2.3;
  3323.         pilot_eye[Z] = -3.0;
  3324.         plane_height = 6.0;
  3325. #ifdef AUDIO
  3326.         thrust_type(0);
  3327. #endif
  3328.         break;
  3329.         case 7:
  3330.         plane_type = F14_NAME;
  3331.         pp->type = F14;
  3332.         s = 565.0;
  3333.         W = 42000.0;
  3334.         fuel_weight = 16200.0;
  3335.         set_fuelgauge(16000.0, 2000.0, 5, 1000);
  3336.         Mthrust = 55000.0;
  3337.         b = 64.0;
  3338.         ef = .87;
  3339.         Lmax = 8.0;    Lmin = -4.0;
  3340.         Fmax = 40;    Smax = 60;
  3341.         set_flapspoiler(40, 40, 4, 60, 60, 6);
  3342.         MAX_RK = 4;    MAX_SW = 4;
  3343.         swpos[3][X] =   9.0; swpos[3][Y] =  0.0; swpos[3][Z] = 3.0;
  3344.         swpos[2][X] =  -9.0; swpos[2][Y] =  0.0; swpos[2][Z] = 3.0;
  3345.         swpos[1][X] =   9.0; swpos[1][Y] =  0.0; swpos[1][Z] = 3.0;
  3346.         swpos[0][X] =  -9.0; swpos[0][Y] =  0.0; swpos[0][Z] = 3.0;
  3347.         rkpos[3][X] =  -2.0; rkpos[3][Y] = -1.0; rkpos[3][Z] = 3.0;
  3348.         rkpos[2][X] =   2.0; rkpos[2][Y] = -1.0; rkpos[2][Z] = 3.0;
  3349.         rkpos[1][X] =  -2.0; rkpos[1][Y] = -1.0; rkpos[1][Z] = 3.0;
  3350.         rkpos[0][X] =   2.0; rkpos[0][Y] = -1.0; rkpos[0][Z] = 3.0;
  3351.         MIN_LIFT_SPEED = 90;
  3352.         ELEVF = 32.0;
  3353.         ROLLF = 130.0;
  3354.         pilot_eye[Y] = 4.8;
  3355.         pilot_eye[Z] = -26.0;
  3356.         plane_height = 4.89;
  3357. #ifdef AUDIO
  3358.         thrust_type(1);
  3359. #endif
  3360.         break;
  3361.         case 8:
  3362.         plane_type = B727_NAME;
  3363.         pp->type = B727;
  3364.         s = 1700.0;        /* wing area in sq. feet    */
  3365.         W = 101773.0;        /* weight of plane in lbs.    */
  3366.         fuel_weight = 59750.0;
  3367.         Mthrust = 48000.0;    /* maximum thrust        */
  3368.         set_fuelgauge(48000.0, 8000.0, 5, 1000);
  3369.         b = 108.0;        /* wing span in feet        */
  3370.         ef = .83;        /* efficiency factor        */
  3371.         Lmax = 4.0;        /* maximum lift before wing breaks */
  3372.         Lmin = -2.0;        /* minimum lift before wing breaks */
  3373.         Fmax = 50;        /* maximum flap deflection    */
  3374.         Smax = 80;        /* maximum spoiler deflection    */
  3375.         set_flapspoiler(50, 50, 5, 80, 80, 8);
  3376.         MAX_RK = 0;    MAX_SW = 0;
  3377.         MIN_LIFT_SPEED = 180;
  3378.         ELEVF = 25.0;        /* elevator rate in degrees/sec    */
  3379.         ROLLF = 50.0;        /* roll rate (both at 300 mph)    */
  3380.         pilot_eye[Y] = 2.0;
  3381.         pilot_eye[Z] = -66.0;
  3382.         plane_height = 10.0;
  3383. #ifdef AUDIO
  3384.         thrust_type(1);
  3385. #endif
  3386.         break;
  3387. #if 0
  3388.         case 9:
  3389.         plane_type = STEALTH_NAME;
  3390.         pp->type = STEALTH;
  3391.         s = 1000.0;        /* wing area in sq. feet    */
  3392.         W = 30000.0;        /* weight of plane in lbs.    */
  3393.         fuel_weight = 14000.0;
  3394.         Mthrust = 25000.0;    /* maximum thrust        */
  3395.         set_fuelgauge(10000.0, 120.0, 5, 1000);
  3396.         b = 38.0;        /* wing span in feet        */
  3397.         ef = .85;        /* efficiency factor        */
  3398.         Lmax = 4.0;        /* maximum lift before wing breaks */
  3399.         Lmin = -2.0;        /* minimum lift before wing breaks */
  3400.         Fmax = 30;        /* maximum flap deflection    */
  3401.         Smax = 60;        /* maximum spoiler deflection    */
  3402.         set_flapspoiler(50, 50, 5, 80, 80, 8);
  3403.         MAX_RK = 0;
  3404.         MAX_SW = 4;
  3405.         swpos[3][X] =  14.8; swpos[3][Y] = -2.0; swpos[3][Z] = 4.6334;
  3406.         swpos[2][X] = -14.8; swpos[2][Y] = -2.0; swpos[2][Z] = 4.6334;
  3407.         swpos[1][X] =  12.8; swpos[1][Y] = -2.0; swpos[1][Z] = 4.6334;
  3408.         swpos[0][X] = -12.8; swpos[0][Y] = -2.0; swpos[0][Z] = 4.6334;
  3409.         MIN_LIFT_SPEED = 120;
  3410.         ELEVF = 35.0;        /* elevator rate in degrees/sec    */
  3411.         ROLLF = 170.0;        /* roll rate (both at 300 mph)    */
  3412.         pilot_eye[Y] = 0.0;
  3413.         pilot_eye[Z] = 0.0;
  3414.         plane_height = 10.0;
  3415. #ifdef AUDIO
  3416.         thrust_type(1);
  3417. #endif
  3418.         break;
  3419. #endif
  3420.         case 27-'0':
  3421.         end_of_program();
  3422.     }
  3423.  
  3424.     if (!hud && new_inst)
  3425.     draw_instruments();
  3426. }
  3427.  
  3428.  
  3429. /*
  3430.  *  trash_plane() is called when a plane is blowb up to screw up it's dynamics.
  3431.  */
  3432. trash_plane()
  3433. {
  3434.     s /= 3.0;        /* lower wing area */
  3435.     b /= 2.0;        /* shorten wings */
  3436.     ef = 1.0;        /* lower efficiency factor */
  3437.     Lmax = 1.0;        /* poor maximum lift before wing breaks */
  3438.     Lmin = -1.0;    /* poor minimum lift before wing breaks */
  3439.     max_throttle = 0;
  3440.     throttle = 0;
  3441.  
  3442.     Cdp = .015;                /* coefficient of parasitic drag*/
  3443.     ipi_AR = 1.0/(3.1415927 * b*b/s);    /* 1.0 / pi * wing Aspect Ratio    */
  3444.     ie_pi_AR = ipi_AR/ef;        /* 1.0 / pi * AR * efficiency    */
  3445.     gefy = .7 * b;
  3446.  
  3447.     stick_xadd = flight_random(30);
  3448.     stick_yadd = flight_random(30);
  3449.     sb_xadd = stick_xadd * 10;
  3450.     sb_yadd = stick_yadd * 10;
  3451. }
  3452.  
  3453.  
  3454. launch_missile(mtype)
  3455.     int mtype;
  3456. {
  3457.     float temp;
  3458.     Plane pp = planes[0], ptemp;
  3459.     float *mpos;
  3460.  
  3461.     /*
  3462.      *  if I'm alive and no weapon already fired
  3463.      *  and I am not on the ground
  3464.      */
  3465.     if (pp->status > MEXPLODE && !pp->mstatus && !on_ground)
  3466.     {
  3467.     if (mtype == TYPE_SIDEWINDER && sidewinders > 0)
  3468.     {
  3469.         sidewinders--;
  3470.         pp->mtype = TYPE_SIDEWINDER;
  3471.         pp->mstatus = MSTART;
  3472. #ifdef AUDIO
  3473.         play_samps(misslesample, misslelength);
  3474. #endif
  3475.         if (missile_target == NULL_PLANE_ID)
  3476.         {
  3477.         if (ptemp = find_closest_plane(pp))
  3478.         {
  3479.             missile_target = PLANE_ID(ptemp);
  3480.             sprintf(charbuf, "Sidewinder->%s", ptemp->myname);
  3481.             set_text_meter(0, charbuf, -1);
  3482.         }
  3483.         else
  3484.             set_text_meter(0, "Sidewinder Launched", -1);
  3485.         }
  3486.         else if (ptemp = lookup_plane(missile_target))
  3487.         {
  3488.         sprintf(charbuf, "Sidewinder->%s", ptemp->myname);
  3489.         set_text_meter(0, charbuf, -1);
  3490.         }
  3491.         else
  3492.         set_text_meter(0, "Sidewinder Launched", -1);
  3493.         mpos = swpos[sidewinders];
  3494.         pp->weapon_state &= ~((PS_SW1 >> PS_W_SHIFT) << sidewinders);
  3495.     }
  3496.     else if (mtype == TYPE_ROCKET && rockets > 0)
  3497.     {
  3498.         rockets--;
  3499.         pp->mtype = TYPE_ROCKET;
  3500.         pp->mstatus = MSTART;
  3501. #ifdef AUDIO
  3502.         play_samps(misslesample, misslelength);
  3503. #endif
  3504.         missile_target = NULL_PLANE_ID;
  3505.         set_text_meter(0, "Rocket Launched", -1);
  3506.         mpos = rkpos[rockets];
  3507.         pp->weapon_state &= ~((PS_RK1 >> PS_W_SHIFT) << rockets);
  3508.     }
  3509.     temp = fabs(vy) + fabs(vz);
  3510.     if (mtype == TYPE_CANNON)
  3511.     {
  3512.         pp->mtype = TYPE_CANNON;
  3513.         pp->mstatus = MFINISH + int_tps;
  3514. #ifdef AUDIO
  3515.         play_samps(cannonsample, cannonlength);
  3516. #endif
  3517.         temp = -2000.0/TPS - temp;
  3518.         missile_target = NULL_PLANE_ID;
  3519.         set_text_meter(0, "20mm Cannon Fired", -1);
  3520.     }
  3521.     else
  3522.         temp = -500.0/TPS - temp;
  3523.  
  3524.     if (pp->mstatus)
  3525.     {
  3526.         missile_vx = ptw[2][0] * temp;
  3527.         missile_vy = ptw[2][1] * temp;
  3528.         missile_vz = ptw[2][2] * temp;
  3529.         if (mtype == TYPE_CANNON)
  3530.         {
  3531.         pp->mx = pp->x + missile_vx;
  3532.         pp->my = pp->y + missile_vy;
  3533.         pp->mz = pp->z + missile_vz;
  3534.         }
  3535.         else
  3536.         {
  3537.         mult_vec(ptw, mpos, &pp->mx);
  3538.         }
  3539.         pp->mkill = NULL_PLANE_ID;
  3540.         rebuild_status();
  3541.     }
  3542.     }
  3543. }
  3544.  
  3545.  
  3546. void calc_clip_planes(Matrix mat, float *eye_point)
  3547. {
  3548.     int i;
  3549.  
  3550.     for (i=0; i < 4; i++)
  3551.     {
  3552.     mult_vec(mat, frustum[i], clip_planes[i]);
  3553.     clip_planes[i][3] = -DOT(clip_planes[i], eye_point);
  3554.     }
  3555. }
  3556.  
  3557.  
  3558.